List Prolog程序的代码,用于检查给定列表是否为回文列表,而不使用反向操作
这是如何使用反向操作获取回文 谓词List Prolog程序的代码,用于检查给定列表是否为回文列表,而不使用反向操作,list,prolog,reverse,palindrome,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(
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").
但我想不做反向操作。有人能帮我吗。只需匹配第一个和最后一个元素
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).
为什么不呢
pal([]).
pal([_]).
pal(Pal) :-
append([H|T], [H], Pal),
pal(T).
在我看来,最优雅的方式是使用DCG,如图所示: 最一般的查询:
?- phrase(palindrome, Ps).
具体例子:
?- phrase(palindrome, [a,b,b,a]).
true .
这里有一个选择:
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
. %
这些答案中有很多使用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.
和一个非回文:
[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.
我没有给出一个解决方案,但是考虑佩林(list):-FunReV(列表,[],列表)。对于您的问题,您可以使用append([H | Tail],[H],Pal)并在Tail上使用递归性。为什么要在不反转的情况下这样做?您将采取什么方法,不是在代码中,而是至少在文字中?这确实是最优雅的解决方案。append([H | T],[H],Pal)删除Pal的第一个和最后一个元素,假设它们是相同的(如果不是Pal失败)。我继续递归地使用T。