prolog两个列表完全相同

时间:2014-03-20 21:41:23

标签: list prolog

我想编写一个函数,如果两个列表完全相同(元素的顺序很重要),则返回true。

我试过这种方式:

same([ ], [ ]).   
same([H1|R1], [H2|R2]):-
    H1 == H2,
    same(R1, R2).

当两个列表相同时返回true,如果我有

,我也期望
?- same(X, [1, 2, 3]).

我希望它返回

X = [1, 2, 3].

但如果输入是这样的话,它就不起作用。以下是我得到的一些示例输出:

?- same([1, 2], [1, 2]).

true.

?- same([2, 1], [1, 2]).

false.

?- same(X, [1, 2, 3]).

false.

?- same([1, 2, 3], [1, 2, X]).

false.

如何解决?

1 个答案:

答案 0 :(得分:3)

问题是你正在使用==/2(检查两个项是否实例化相同)而不是=/2(检查两个项是统一的还是统一的)。只需改为统一:

same([], []).

same([H1|R1], [H2|R2]):-
    H1 = H2,
    same(R1, R2).

然后这将有您正在寻找的行为:

| ?- same(X, [1, 2, 3]).

X = [1,2,3] ? a

no
| ?- same([1, 2], [1, 2]).

(1 ms) yes
| ?- same([2, 1], [1, 2]).

no
| ?- same([1, 2, 3], [1, 2, X]).

X = 3

(1 ms) yes
| ?- same([A,B,C], L).

L = [A,B,C]

yes
% In this last example, A, B, and C are variables. So it says L is [A,B,C],
% whatever A, B, and C are.

如果您在Prolog中查询X == 3,并且X未绑定到值3,或者它只是未绑定,则会失败。如果X未绑定且您查询X = 3,则Prolog会将X(绑定)与3统一起来,并且会成功。

有关=/2==/2之间差异的详情,请参阅What is the difference between == and = in Prolog?

您还可以使用maplist获得一个漂亮,紧凑的解决方案。 maplist非常便于迭代列表:

same(L1, L2) :- maplist(=, L1, L2).

此处,统一(=/2)仍然使用与上述完全相同的原因。

<小时/> 最后,正如@Boris指出的那样,在Prolog中,统一谓词将适用于整个列表。在这种情况下,这就足够了:

same(L1, L2) :- L1 = L2.

或等效地:

same(L, L).  % Would unify L1 and L2 queried as same(L1, L2)

如果列表相同,这将成功,或者尝试通过依次统一每个元素来统一它们。

| ?- same([1,2,X], [1,2,3]).    % Or just [1,2,X] = [1,2,3]

X = 3

yes
| ?- same([1,2,X], [1,2,3,4]).  % Or just [1,2,X] = [1,2,3,4]

no

先前更精细的方法被认为是列表处理中的练习以用于说明。但是,用于比较和/或统一列表的最简单和最正确的方法是L1 = L2