sam*_*sam 8 reverse list prolog palindrome dcg
我是否可以获得具有两个参数的递归Prolog谓词,称为reverse,它返回列表的反转:
示例查询和预期结果:
?- reverse([a,b,c], L). L = [c,b,a].
两个参数的递归Prolog谓词,palindrome如果给定列表是回文,则返回true.
具有预期结果的示例查询:
?- palindrome([a,b,c]). false. ?- palindrome([b,a,c,a,b]). true.
广告1:除非您允许辅助谓词,否则无法定义reverse/2为(直接编辑thx到@repeat:tail)递归谓词.
广告2:
palindrome(X) :- reverse(X,X).
Run Code Online (Sandbox Code Playgroud)
但最简单的方法是使用DCG定义这样的谓词:
iseq([]) --> [].
iseq([E|Es]) --> iseq(Es), [E].
reverse(Xs, Ys) :-
phrase(iseq(Xs), Ys).
palindrome(Xs) :-
phrase(palindrome, Xs).
palindrome --> [].
palindrome --> [E].
palindrome --> [E], palindrome, [E].
Run Code Online (Sandbox Code Playgroud)
在reverse/2没有使用某些辅助谓词的情况下,没有一种有效的方法来定义单个递归定义.但是,如果允许这样做,那么一个不依赖于任何内置函数的简单解决方案append/3(并且应该适用于大多数Prolog实现)将使用累加器列表,如下所示:
rev([],[]).
rev([X|Xs], R) :-
rev_acc(Xs, [X], R).
rev_acc([], R, R).
rev_acc([X|Xs], Acc, R) :-
rev_acc(Xs, [X|Acc], R).
Run Code Online (Sandbox Code Playgroud)
rev/2是反转谓词,它简单地"委托"(或包装)基于累加器的版本rev-acc/2,该版本以递减的顺序将输入列表的元素添加到累加器中.
运行这个:
?- rev([1,3,2,x,4],L).
L = [4, x, 2, 3, 1].
Run Code Online (Sandbox Code Playgroud)
事实上@false已经指出(+1),
palindrome(X) :- rev(X,X).
Run Code Online (Sandbox Code Playgroud)