Prolog程序代码,用于在不使用反向操作的情况下检查给定列表是否为回文序列

时间:2014-12-15 09:09:23

标签: list prolog reverse palindrome

这是如何使用反向操作获得回文。

谓词

palin(list)
findrev(list,list,list)
compare(list,list)

条款

palin(List1):-
    findrev(List1,[],List2),
    compare(List1,List2).

findrev([],List1,List1).

findrev([X|Tail],List1,List2):-
    findrev(Tail,[X|List1],List2).

compare([],[]):-
    write("\nList is Palindrome").

compare([X|List1],[X|List2]):-
    compare(List1,List2).    

compare([X|List1],[Y|List2]):-
    write("\nList is not Palindrome").

但我想在没有反向操作的情况下这样做。有人可以帮助我。

5 个答案:

答案 0 :(得分:4)

在我看来,最优雅的方式是使用DCG,如图here所示:

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

最常见的查询:

?- phrase(palindrome, Ps).

具体例子:

?- phrase(palindrome, [a,b,b,a]).
true .

答案 1 :(得分:3)

为什么不

pal([]).
pal([_]).
pal(Pal) :-
    append([H|T], [H], Pal),
    pal(T).

答案 2 :(得分:2)

只匹配第一个和最后一个元素。

first([F|L], F, L). % better inlined, but for clarity...
last(Es, L, R) :- append(R, [L], Es). % again...

palin([]).
palin([_]).
palin(L) :-
  first(L, E, X), last(X, E, Y), palin(Y).

答案 3 :(得分:1)

这是一个选项:

palindrome( Xs ) :- palindrome( Xs , [] , Xs ) .

palindrome( []     , Z , X ) .
palindrome( [X|Xs] , T , Z ) :- palindrome( Xs , [X|T] , Z ) .

虽然它实际上只是推出了reverse/2的实现。

另一种选择,使用append/3

palindrome( [] ) .
palindrome( Xs ) :- append( [X|Rest] , [X] , Xs ) , palindrome(Rest) .

第三种选择,完全避免append/3

palindrome( []      ) .                    % The empty list is a palindrome
palindrome( [X]     ) .                    % A single-element list is a palindrome.
palindrome( [X,Y|Z] ) :-                   % A list of more than one element is a palindrome, IF...
  first( Xs , X , L1 ) ,                   % The first element and
  last(  L1 , X , L2 ) ,                   % The last element are identical, AND
  palindrome(T2)                           % what's left over is a palindrome, too.
  .

first( [X|Xs] , X , Xs ) .      % getting the first item from a list is trivial.

last( [X]     , X , []    ) .   % getting the last item from a single element list is trivial, too.
last( [X,Y|Z] , L , [X|R] ) :-  % otherwise...add the head of the list to the leftovers list,
   last( [Y|Z] , L , R )        % - and recurse down on the tail
   .                            %

答案 4 :(得分:0)

很多这些答案都使用了last或append,这些都是昂贵的操作。

您可以执行一半反向,然后检查相等性。 问题规定不使用反向,但这只使用反向过程,而不是完全反向。

palindrome(Xs):- palindrome(Xs,[]).

palindrome(Xs, Xs).                    % [1,2,2,1] will get to pal([1,2],[1,2])
palindrome([X|Xs],Xs).                 % captures a case like [a,b,c,b,a]
palindrome([X|Xs],Ys):- palindrome(Xs, [X|Ys]).      % reverse-like process

上面可能遗漏的一件事是削减。虽然这里没有必要,但应该用于良好实践:

palindrome(Xs):- palindrome(Xs,[]).

palindrome(Xs, Xs):- !.                    % Don't need to redo after positive match
palindrome([X|Xs],Xs):- !.                 
palindrome([X|Xs],Ys):- palindrome(Xs, [X|Ys]). 

回文的典型痕迹:

[trace] 88 ?- pal([1,2,1]).
   Call: (6) pal([1, 2, 1]) ? creep
   Call: (7) pal([1, 2, 1], []) ? creep
   Call: (8) pal([2, 1], [1]) ? creep
   Exit: (8) pal([2, 1], [1]) ? creep         % Matches rule - palindrome([X|Xs],Xs).
   Exit: (7) pal([1, 2, 1], []) ? creep
   Exit: (6) pal([1, 2, 1]) ? creep
true .

非回文:

[trace] 87 ?- pal([1,2,3]).
Call: (6) pal([1, 2, 3]) ? creep
   Call: (7) pal([1, 2, 3], []) ? creep
   Call: (8) pal([2, 3], [1]) ? creep
   Call: (9) pal([3], [2, 1]) ? creep
   Call: (10) pal([], [3, 2, 1]) ? creep
   Fail: (10) pal([], [3, 2, 1]) ? creep      % Fails as [] doesn't equal [3,2,1] and can't be pulled apart
   Fail: (9) pal([3], [2, 1]) ? creep
   Fail: (8) pal([2, 3], [1]) ? creep
   Fail: (7) pal([1, 2, 3], []) ? creep
   Fail: (6) pal([1, 2, 3]) ? creep
false.