Prolog初学者:仅反转一次

时间:2015-11-24 13:26:50

标签: list prolog reverse

假设我有两个任意列表代表3位谓词的前两项:

[anna,berta,charlotte],[charles,bob,andy]

我希望匹配第三个列表中的每个项目(3位谓词的第三项),如下所示:

[[anna,andy],[berta,bob],[charlotte,charles]]

基本上,项目以顺序反向方式匹配。为了按顺序匹配项目,我设计了以下代码:

match([],[],[]).
match([A|At],[C|Ct],[[A,C]|Dt]):-match(At,Ct,Dt).

但这会给我以下内容:

match([anna,berta,charlotte],[charles,bob,andy],X).
X=[[anna,charles],[berta,bob],[charlotte,andy]]

所以我需要以某种方式反转第二个列表。到目前为止,我已将代码更改为:

match([],[],[]).
match([A|At],[C|Ct],[[A,B]|Dt]):-reverse([C|Ct],[B|Bt]),match(At,Bt,Dt).

但是这会在每次传球时不断反转第二个列表。结果如下:

match([anna,berta,charlotte],[charles,bob,andy],X).
X=[[anna,andy],[berta,charles],[charlotte,bob]]

问题: 如何仅反转第二个列表,因此实际结果与所需的结果相符?或者我的方法是否存在根本缺陷?我是prolog的新手,目前我对此感到不安。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

完全按照您的说法进行操作:将列表翻转一次,然后使用反向列表。

lists_pairs(Ps1, Ps2, Pairs) :-
    reverse(Ps2, RPs2),
    pairs_keys_values(Pairs, Ps1, RPs2).

您可以在任何体面的Prolog库中查看reverse/2pairs_keys_values/3的源代码,看看它是如何定义的。

示例查询和回答:

?- lists_pairs([anna,berta,charlotte], [charles,bob,andy], Ps). 
Ps = [anna-andy, berta-bob, charlotte-charles].

我将这些配对转换为非敏感的配对列表"表示为练习。

答案 1 :(得分:2)

解决需要您仅应用规则一次的问题的技巧是构建一个辅助规则,该规则在调用递归规则之前和/或之后执行额外的步骤:

match(A, B, R) :- reverse(B, RevB), match_impl(A, RevB, R).

match_impl([], [], []).
match_impl([A|At], [C|Ct], [[A,C]|Dt]) :- match_impl(At, Ct, Dt).

match_impl/3是您重命名的match/3规则,以避免与" top" match/3规则包含辅助步骤。

答案 2 :(得分:2)

这是@mat's answer的一个小跟进。

为了在某些情况下帮助终止,您可以添加冗余的same_length_as/3目标,如下所示:

lists_pairs(Ps1, Ps2, Pairs) :- 
   same_length_as(Ps1, Ps2, Pairs),
   reverse(Ps2, RPs2),
   pairs_keys_values(Pairs, Ps1, RPs2).

辅助谓词same_length_as/3可以这样定义:

same_length_as([],[],[]).
same_length_as([_|As],[_|Bs],[_|Cs]) :-
   same_length_as(As,Bs,Cs).