views:

184

answers:

2

Is there a way to test wether an arbitrary list is symmetric?

For example:

?- symmetric([a,b,b,a]).
true.

?- symmetric([a,b,c,a]).
false.

?- symmetric([a,a]).
true.

My attemp was to compare the first element to the last element and if they are equal to remove them and proceed with the rest of the list; otherwise fail. Succeed if the list has 2 elements and they are equal. Otherwise fail.

However "finding" the end of the list using this predicate is not really performant:

last(L,[L]).
last(L,[H|T]):-last(L,T).

Does anyone know of a good way to do this? Any help would really be appreciated!

Btw: I don't care for lists with an uneven amount of elements.

+2  A: 

I found the answer to my question.

A symmetric list is a palindrome (Sometimes you don't see see the forest for the trees)... And this simple predicate tests for that:

is_palindrome(L) :- reverse(L,L).
Chris
the simplest answers are the best...
jon hanson
+1  A: 

But your algorithm was interesting nevertheless. There is a last/2 built-in (at least in SWI Prolog) that doesn't suffer from the performance penalty of your recursive approach. With this, here is a version that implements your idea:

symmetric([]).
symmetric([L]).
symmetric([H|T]):-
    last(T,H),        % this forces the last element to equal the first
    append(T1,[H],T), % this deconstructs the rest list in one without the last elem.
    symmetric(T1).    % and recurses on that

Interesting is the use of the append/3 predicate, to deconstruct the initial rest list into the rest list without the last element.

EDIT: I realized I can do even without last/2, just with append/3. So here is the improved version:

symmetric([]).
symmetric([L]).
symmetric([H|T]):-
    append(T1,[H],T), % deconstruct and assure symmetry
    symmetric(T1).    % and recurse

Now, here append does both, the deconstruction to get T1, as well as assuring that the last element of the list matches the first :-).

ThomasH