Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!swrinde!ihnp4.ucsd.edu!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!lee
From: lee@munta.cs.mu.OZ.AU (Lee Naish)
Subject: Re: Need some assistance!.
Message-ID: <9504617.3604@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU (CS-Usenet)
Organization: Department of Computer Sci, University of Melbourne
References: <Pine.A32.3.91.950212061326.159242A-100000@blue.weeg.uiowa.edu>
Date: Wed, 15 Feb 1995 06:06:06 GMT
Lines: 139

In article <Pine.A32.3.91.950212061326.159242A-100000@blue.weeg.uiowa.edu> "G. Dhingra" <gdhingra@blue.weeg.uiowa.edu> writes:
>Hi!,
>
>It has been a while since I worked with prolog but can one tell me a 
>succinct was of writing the predicate definition for Palindrome(A).

I just so happen to have a collection of palindrome definitions...

	lee

	% Justin's version
	% takes elements from the head of list and
	% puts then onto the head of an initially
	% empty list until the two lists unify
	% (more or less)
p1(X) :-
	p1a(X, []).

p1a(X, X).
p1a(_.X, X).
p1a(A.X, Y) :-
	p1a(X, A.Y).

	% append + reverse version (inefficient but cute)
p2(X) :-
	append(A, B, X),
	reverse(A, B).
p2(X) :-
	append(A, _.B, X),
	reverse(A, B).

	% (slightly) better append + reverse version
p3([]).
p3(X) :-
	append(A, B.C, X),
	(	reverse(A, B.C)
	;	
		reverse(A, C)
	).

	% tricky version
	% Basic idea is to figure out the length of the list
	% then unify the reversed first half with the second half.
	% This version avoids a separate first scan to find the length.
	% It uses two "copies" of X (two pointers two same structure)
	% - one to represent the length
	% - one for the elements
	% plus accumulator for reversed front of list
	% no choice points are created
p4(X) :-
	p4a(X, X, []).

p4a([], X, X).		% even length
p4a(_.L, X, As) :-
	p4b(L, X, As).

p4b([], _.X, X).	% odd length
p4b(_.L, A.X, As) :-
	p4a(L, X, A.As).

	% version using arg etc
	% doesn't work on long lists if there is a max arity
	% Copies elements of list into arguments of a (big) complex
	% term, uses functor to find out how many args there are,
	% then uses arg to unify pairs of args.
	% no choice points are created with NU-Prolog
	% uses a bit less space than previous version (L+1 words
	% instead of L/2*3 words)
p5(X) :-
	T =.. f.X,
	functor(T, _, N),
	H is N // 2,
	p5a(1, H, N, T).

p5a(F, H, N, T) :-
	( F =< H ->
		arg(F, T, A),
		arg(N, T, A),
		F1 is F + 1,
		N1 is N - 1,
		p5a(F1, H, N1, T)
	;
		true
	).

	% version from Sterling & Shapiro
	% "The Art of Prolog" MIT Press
	% - unfolded NDFA
	% (with most bugs & typos fixed!)
p6(X) :-
	p6a(q0, X, []).

p6a(q0, X.Xs, S) :-
	p6a(q0, Xs, X.S).
p6a(q0, X.Xs, S) :-
	p6a(q1, Xs, X.S).
p6a(q0, X.Xs, S) :-
	p6a(q1, Xs, S).
p6a(q1, X.Xs, X.S) :-
	p6a(q1, Xs, S).
p6a(q1, [], []).

	% above program optimized further
	% Basically this use the same algorithm as Justin's
	% program but doesn't uses unification to do equality
	% of lists, leaves lots more choice points around,
	% and fails with the empty list.
p7(X) :-
	p7a_q0(X, []).

p7a_q0(X.Xs, S) :-
	p7a_q0(Xs, X.S).
p7a_q0(X.Xs, S) :-
	p7a_q1(Xs, X.S).
p7a_q0(X.Xs, S) :-
	p7a_q1(Xs, S).

	% this just tests equality of lists (inefficient)
p7a_q1(X.Xs, X.S) :-
	p7a_q1(Xs, S).
p7a_q1([], []).

	% Jeroen's version
	% straightforward recursive solution
	% coding could be optimized further
	% but complexity of algorithm is not good
p8([]).
p8([_]).
p8(Head.Tail) :-
	append(Tail1, [Last], Tail),
	Head = Last,
	p8(Tail1).

	% Fergus' version %	
	% The shortest and reasonably efficient also %	
p9(X):-reverse(X,X). % .)X,X(esrever-:)X(9p
	% osla tneiciffe ylbanosaerdna tsetrohs ehT %	
	% noisrev 'sugreF %	

