【问题标题】:Prolog copy a specific letter from a list to another in the same placeProlog将列表中的特定字母复制到同一位置的另一个字母
【发布时间】:2016-05-15 14:05:29
【问题描述】:

所以我试图在 prolog 中创建一个方法来获取一个字符和 2 个列表,无论在列表 1 中找到该字符的任何位置,我都会将该字符注入到列表 2 中。该方法返回的新状态清单 2. 即使我认为它是正确的,它似乎也不起作用。这是我的代码。

transfer([],[],_,[])
transfer([H¦T],[_¦T1],C,R):-
    transfer(T,T1,C,R1),
    H==C,
    append([H],R1,R).

如果我执行 ?- transfer([h,e,l,l,o],[0,0,0,0,0],e,X)。我会得到 X=[0,e,0,0,0] 的结果。有什么想法吗?

【问题讨论】:

  • 一些想法:(1)[H,T][_,T1] 是仅包含两个元素的列表。因此,您的谓词不能与空列表或具有 2 个元素的列表以外的参数一起使用。您需要检查列表语法。 (2)append([H], R1, R)可以替换为R = [H|R1]。 (3) 您正在使用匿名变量 _ 来表示您在解决方案中实际上可能关心的列表元素。所以应该是“不在乎”。

标签: list prolog character


【解决方案1】:

想想你的谓词应该描述什么关系。如果前两个列表为空,则最后一个参数也是一个空列表,无论比较元素如何。这是您已经拥有的基本案例。否则你有两种互斥的情况:

  1. 第一个列表的头部等于比较元素。在这种情况下,比较元素在结果列表中。

  2. 第一个列表的头部与比较元素不同。在这种情况下,第二个列表的头部位于结果列表中。

您可以使用或谓词; 对这种情况区分进行建模。那么 transfer/4 可能看起来像这样:

transfer([],[],_,[]).
transfer([H1|T1],[H2|T2],C,[R|Rs]):-
   ((H1=C,R=C);(dif(H1,C),R=H2)),     % case 1 or case 2
   transfer(T1,T2,C,Rs).              % the relation holds for the tails as well

使用此定义,您的示例查询会产生所需的结果:

   ?- transfer([h,e,l,l,o],[0,0,0,0,0],e,X).
X = [0,e,0,0,0] ? ;
no

或者,您也可以在单独的谓词中描述上述大小写区别,然后使用 maplist/4 将关系应用于三个列表:

:- use_module(library(apply)).

e_x_y_z(E,X,Y,Z) :-
   (X=E,Z=E);(dif(X,E),Z=Y).

transfer(L1,L2,C,R) :-
   maplist(e_x_y_z(C),L1,L2,R).

我发现这个版本更容易阅读,因为实际关系的定义与递归是分开的。注意 e_x_y_z/4 中的比较元素是第一个参数,因此可以将谓词传递给 maplist/4,而三个列表的元素分别缺少三个参数。

【讨论】:

  • 这太棒了!非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多