繁体   English   中英

反向/回文的递归 Prolog 谓词

[英]Recursive Prolog predicate for reverse / palindrome

  1. 我可以得到一个递归 Prolog 谓词,它有两个参数,称为 reverse,它返回一个列表的逆:

    示例查询和预期结果:

    \n ?- 反向([a,b,c],L)。\n L = [c,b,a]。\n
  2. 称为palindrome的两个参数的递归 Prolog 谓词,如果给定列表是回文,则返回 true。

    具有预期结果的示例查询:

    \n ?- 回文([a,b,c])。\n错误的。\n\n ?- 回文([b,a,c,a,b])。\n真的。\n

广告 1:不可能将reverse/2定义为(直接将thx 编辑为 @repeat: tail)递归谓词 - 除非您允许使用辅助谓词。

广告 2:

palindrome(X) :- reverse(X,X).

但最简单的方法是用 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].

在不使用一些辅助谓词的情况下,没有一种有效的方法可以使用单个递归定义来定义reverse/2 但是,如果这仍然被允许,一个不依赖于任何内置函数(如append/3 (并且应该适用于大多数 Prolog 实现)的简单解决方案是使用accumulator list ,如下所示:

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).

rev/2是反转谓词,它简单地“委托”(或包装)基于累加器的版本,称为rev-acc/2 ,它以相反的顺序递归地将输入列表的元素添加到累加器中。

运行这个:

?- rev([1,3,2,x,4],L).
L = [4, x, 2, 3, 1].

事实上正如@false 已经指出的那样 (+1),

palindrome(X) :- rev(X,X). 

只是为了好奇,这里有一个 reverse/2 的递归实现,它不使用辅助谓词并仍然反转列表。 您可能会认为它在作弊,因为它使用 reverse/2 使用列表和结构 -/2 作为参数。

reverse([], []):-!.
reverse([], R-R).
reverse(R-[], R):-!.
reverse(R-NR, R-NR).
reverse([Head|Tail], Reversed):-
  reverse(Tail, R-[Head|NR]),
  reverse(R-NR, Reversed).
conca([],L,L).
conca([X|L1],L2,[X|L3]):- conca(L1,L2,L3).
rev([],[]).
rev([X|Y],N):- rev(Y,N1),conca(N1,[X],N).
palindrome([X|Y]):- rev([X|Y],N),equal([X|Y],N).
equal([X],[X]).
equal([X|Y],[X|Z]):- equal(Y,Z).

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM