4

I tried to write a palindrome program by using lists. However, I have to use difference lists and output should be:

The ith element of the list is the same of (n-i+1)th element of the list and n is the length of the list. For example, [a,X,c,b,Y] should give X = b and Y = a.

So far I have implemented:

% length of the list 
len([], 0).
len([H|T], B) :-
   len(T, NT),
   B is NT + 1.

% return the ith element of the list 
match([H|_], 0, H) :-
   !.
match([_|T], N, H) :-
   N > 0,
   N1 is N-1,
   match(T, N1, H).

How do I complete this?

A-Tech
  • 806
  • 6
  • 22
limonik
  • 499
  • 1
  • 6
  • 28
  • 1
    Prolog already has `length/2`, so you don't need to write your own list length predicate (`len/2`). There's also a Prolog predicate to return the n-th element of a list, (see SWI Prolog's `nth0/3` or `nth1/3`). Also, what you're describing is a *palindrome*. You can probably find several examples to work from by searching for, "prolog palindrome". – lurker Jun 30 '15 at 11:10
  • possible duplicate of [Understanding difference lists (Prolog)](http://stackoverflow.com/questions/20169862/understanding-difference-lists-prolog) – fferri Jun 30 '15 at 13:03
  • @mescalinum i dont think so. I also searched other questions about palindrome. Could you please help me – limonik Jul 01 '15 at 10:51

1 Answers1

6

Use definite clause grammars!

DCG, a major Prolog feature, makes using difference lists easy—enabling you to write concise and efficient code with little effort!

Want to know more? Just follow the dots:

Without any further ado, let's get to the code:

palindrome --> [].
palindrome --> [_].
palindrome --> [X], palindrome, [X].

% Alternatively, we could also use the following more compact definition:
palindrome --> [] | [_] | [X], palindrome, [X].

Done. Let's run a few queries! First, the query the OP gave:

?- phrase(palindrome, [a,X,c,b,Y]).
   X = b, Y = a
;  false.

In German, "corn" is called "mais". If we put "siam" (the old name of "the Kingdom of Thailand") in front, we get a delicious palindrome:

?- set_prolog_flag(double_quotes, chars).
true.

?- phrase(palindrome, "siammais").
   true
;  false.

?- phrase(palindrome, "siamais").       % or kick one middle 'm' character
   true                                 % ... for an odd-length palindrome
;  false.

At last, let's not forget about the most general query:

?- phrase(palindrome, Xs).
   Xs = []
;  Xs = [_A]
;  Xs = [_A,_A]
;  Xs = [_A,_B,_A]
;  Xs = [_A,_B,_B,_A]
;  Xs = [_A,_B,_C,_B,_A]
...

On the we can use the built-in Prolog predicate listing/1 to peek at the code the DCG was "translated" to—at this level the internal use of becomes apparent:

?- listing(palindrome//0).
palindrome(A, A).
palindrome([_|A], A).
palindrome([C|A], D) :-
    palindrome(A, B),
    B = [C|D].

true.
repeat
  • 18,496
  • 4
  • 54
  • 166