【问题标题】:Prolog Beginner: Reverse List only onceProlog 初学者:仅反向列表一次
【发布时间】:2015-11-24 13:26:49
【问题描述】:

假设我有两个任意列表,代表 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 的新手,目前对此感到困惑。任何帮助将不胜感激。

【问题讨论】:

    标签: list prolog reverse


    【解决方案1】:

    照你说的做:反转列表一次,然后使用反转的列表。

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

    我将这些对转换为不合理的“列表对”表示形式作为练习。

    【讨论】:

    • s(X) 用于使用干净的数据表示。
    【解决方案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 规则重命名以避免与包含辅助步骤的“顶部”match/3 规则冲突。

    【讨论】:

      【解决方案3】:

      这是@mat's answer 的一个小后续。

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

      列表对(Ps1,Ps2,对):- same_length_as(Ps1, Ps2, Pairs), 反向(Ps2,RPs2), pair_keys_values(对,Ps1,RPs2)。

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

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

      【讨论】:

      • maplist(\_^_^_^true, Ps1,Ps2, Pairs)
      猜你喜欢
      • 2015-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多