这是如何使用反向操作获得回文。
谓词
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").
但我想在没有反向操作的情况下这样做。有人可以帮助我。
答案 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.