Prolog检查列表中的第一个元素是否不相等,列表中的第二个元素是否相等

时间:2018-11-22 19:46:30

标签: list prolog

我想比较2个列表,第一个元素不应该相等,第二个元素应该相等。

示例数据库:

likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).

因此对于相同的内容([josh,muse],[sam,muse]),它应该返回true。

这是我到目前为止尝试过的:

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

每个组合都返回false。

2 个答案:

答案 0 :(得分:1)

您在[Head|Tail]谓词的定义中使用的列表的same/2序言符号可访问列表 head tail 。列表的尾部本身就是一个(可能为空)列表。但是在您的情况下,您想访问第一个和第二个元素,您可以通过编写[First, Second| _]来实现(即,枚举用逗号分隔的元素;这里我使用的是匿名变量作为尾巴,因为我们不需要它,因此我们可以忽略它)。

您的谓词可以通过将其重写为以下形式来固定:

same([F1,S1|_], [F2,S2|_]):-
    F1 \== F2,
    S1 == S2.

如果您知道参数始终是包含两个元素的列表,则可以将谓词简化为:

same([F1,S1], [F2,S2]):-
    F1 \== F2,
    S1 == S2.

通话示例:

?- same([josh,muse], [sam,muse]).
true.

?- same([sam,muse], [sam,muse]).
false.

?- same([josh,muse], [sam,maria]).
false.

最后一点,您的问题是关于术语相等性的,但是在解决方案尝试中,您正在使用术语统一性。它们具有不同的语义,不应混淆。

答案 1 :(得分:1)

在阅读您的问题时,您首先提供了一个事实数据库

likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).

但随后将列表用作谓词

same([josh,muse], [sam,muse]).

Paulo从清单开始回答,我将从事实开始回答。

第一件事是创建一个谓词,以读取事实,执行一些逻辑并返回结果。

same_1(P1,P2,Item) :-
    likes(P1,Item),
    likes(P2,Item).

给出

?- same_1(P1,P2,Item).
P1 = P2, P2 = josh,
Item = muse ;
P1 = josh,
P2 = sam,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
P1 = P2, P2 = sam,
Item = muse ;
P1 = P2, P2 = josh,
Item = gnr ;
P1 = P2, P2 = sam,
Item = radiohead.

因此,需要确保P1与P2不同。

same_2(P1,P2,Item) :-
    likes(P1,Item),
    likes(P2,Item),
    P1 \= P2.

给出

?- same_2(P1,P2,Item).
P1 = josh,
P2 = sam,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
false.

仍然有两个有效答案,但本质上是重复的。要删除这些重复项,需要存储所有结果,以便可以对照现有结果检查每个新结果,而不将其添加到当前结果中。同样,在存储结果之前,还需要对它们进行规范化处理,以便无论在最初创建时以哪种方式对名称进行排序,在保存之前进行比较时,它们的顺序都相同。

修改代码以创建规范化的条目。

same_3(P1,P2,Item) :-
    likes(T1,Item),
    likes(T2,Item),
    T1 \= T2,
    normalize(T1,T2,P1,P2).

normalize(P1,P2,P1,P2) :- P1 @> P2.
normalize(P1,P2,P2,P1) :- P1 @=< P2.

返回

?- same_3(P1,P2,Item).
P1 = sam,
P2 = josh,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
false.

请注意,此结果的名称顺序相同。

现在仅保存结果生成时的结果,并仅向结果中添加唯一项。这是通过setof/3完成的。

?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
Bag = [(sam, josh, muse)].