2
votes

HI I would like to know how a method that finds out if two members of a list in Prolog are adjacent as the catch is that the first and the last elements are checked if they are adjacent something like

  (b,c,[b,a,d,c])

would give yes they are adjacent. I already have this code

adjacent(X, Y, [X,Y|_]).
adjacent(X, Y, [_|Tail]) :-
    adjacent(X, Y, Tail).

but I do not know how to include the head of the list and the last elments as well being compared for being adjacent. If you are really good maybe you can tell me also how it is possible to make something like this

(c,b,[a,b,c,d]) to be true I mean the elements are adjacent no matter which exactly is first.

2

2 Answers

1
votes

You can make use of last/2 predicate [swi-doc] to obtain the last element of the list. But you can not use this in the recursive call, since otherwise it will each element in the list pair with the last element as well.

The trick is to make a helper predicate for the recursive part, and then make the adjacent/3 predicate to call the recursive one you wrote yourself, or one where we match with the last element:

adjacent(X, Y, L) :-
    adj(X, Y, L).
adjacent(X, Y, [Y|T]) :-
    last(T, X).

adj(X, Y, [X,Y|_]).
adj(X, Y, [_|T]) :-
    adj(X, Y, T).
1
votes

Relations about lists can often be described with a Definite Clause Grammar .

A first attempt might be:

adjacent(A, B, L) :-
   phrase(adjacent(A, B), L).  % interface to DCG

adjacent(A,B) -->
   ..., ( [A,B] | [B,A] ), ... .

... --> [] | [_], ... .

Yet, this leaves out cases like adjacent(a,d,[a,b,c,d]). One possibility would be to add another rule, or maybe simply extend the list to be considered.

adjacent(A, B, L) :-
   L = [E,_|_],
   append(L, [E], M),
   phrase(adjacent(A, B), L).