3
votes

I got an assignment where I need to write a predicate "same_position(L1,L2,E1,E2)" where L1 and L2 are lists, E1 is a element from L1 and E2 is a element from L2. the predicate is true when E1 and E2 are in the same positions in their lists. I need to solve this problem using recursion

this is my solution to the problem:

same_position([L1|_],[L2|_],E1,E2) :- L1==E1,L2==E2.
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

this works, but not fully as expected, along with the assignment came a sample output where the below part is the problem. The expected output gives values for L before printing false where mine solution simply prints false. what am I doing wrong?

Expected output:

?- same_position(L, [a,a,c], 3, a).
L = [3|_G1667] ;
L = [_G1769, 3|_G1772] ;
false.

Mine output:

?- same_position(L,[a,a,c],3,a).
false.
1
Perhaps first define predicates that solve the problem for lists with one element, then for lists with two elements, and then aim to generalzie this.Willem Van Onsem

1 Answers

1
votes

The culprit is:

same_position([L1|_],[L2|_],E1,E2) :- L1==E1, L2==E2.
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

The (==)/2 [swi-doc] predicate is defined as:

@Term1 == @Term2

True if Term1 is equivalent to Term2. A variable is only identical to a sharing variable.

So that means that for a variable X, only X == X holds, not X == Y (unless X = Y), and X == 3 always fails (unless X was already grounded to 3).

Based on your sample output, you however do not want to check equality, you want to unify, which is what (=)/2 does:

same_position([L1|_],[L2|_],E1,E2) :- L1 = E1, L2 = E2.
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

In Prolog however, we can also inify in the head, by using the same variable twice (or more) in the head:

same_position([L1|_],[L2|_], L1, L2).
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).