首页 > 解决方案 > SWI-Prolog 检查不同列表中的两个元素是否在同一位置

问题描述

我得到了一个任务,我需要编写一个谓词“same_position(L1,L2,E1,E2)”,其中 L1 和 L2 是列表,E1 是 L1 中的元素,E2 是 L2 中的元素。当 E1 和 E2 在其列表中的相同位置时,谓词为真。我需要使用递归来解决这个问题

这是我对问题的解决方案:

same_position([L1|_],[L2|_],E1,E2) :- L1==E1,L2==E2.
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

这可行,但并不完全符合预期,伴随着分配而来的是一个示例输出,其中以下部分是问题所在。预期的输出在打印 false 之前给出 L 的值,而我的解决方案只是打印 false。我究竟做错了什么?

预期输出:

?- same_position(L, [a,a,c], 3, a).
L = [3|_G1667] ;
L = [_G1769, 3|_G1772] ;
false.

矿井输出:

?- same_position(L,[a,a,c],3,a).
false.

标签: prolog

解决方案


罪魁祸首是:

same_position([L1|_],[L2|_],E1,E2) :- L1==E1, L2==E2.
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

[ (==)/2swi-doc]谓词定义为:

@Term1 == @Term2

True如果Term1相当于Term2. 变量仅与共享变量相同。

所以这意味着对于一个变量X,只X == X成立,而不是X == Y(除非X = Y),并且X == 3总是失败(除非X已经接地3

但是,根据您的示例输出,您不想检查相等性,而是要unify,这就是(=)/2

same_position([L1|_],[L2|_],E1,E2) :- L1 = E1, L2 = E2.
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

然而,在 Prolog 中,我们也可以在 head 中进行 inify,方法是在head中使用相同的变量两次(或更多):

same_position([L1|_],[L2|_], L1, L2).
same_position([_|L1],[_|L2],E1,E2) :- same_position(L1,L2,E1,E2).

推荐阅读