首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Prolog检查列表中的第一个元素是否不相等,列表中的第二项是否相等

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

Stack Overflow用户
提问于 2018-11-23 03:46:30
回答 2查看 1.3K关注 0票数 1

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

示例数据库:

代码语言:javascript
运行
复制
likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).

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

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

代码语言:javascript
运行
复制
same([H1|R1], [H2|R2]):-
    H1 \= H2,
    same(R1,R2).

这将为每个组合返回false。

EN

回答 2

Stack Overflow用户

发布于 2018-11-23 04:17:10

您在same/2谓词的定义中使用的列表的[Head|Tail] Prolog表示法提供了对列表头部和尾部的访问。列表的尾部本身就是一个(可能是空的)列表。但在本例中,您希望访问第一个和第二个元素,这可以通过编写[First, Second| _]来实现(即,通过枚举由逗号分隔的元素;在这里,我使用一个匿名变量作为尾部,因为我们不需要它,因此可以忽略它)。

您的谓词可以通过将其重写为:

代码语言:javascript
运行
复制
same([F1,S1|_], [F2,S2|_]):-
    F1 \== F2,
    S1 == S2.

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

代码语言:javascript
运行
复制
same([F1,S1], [F2,S2]):-
    F1 \== F2,
    S1 == S2.

示例调用:

代码语言:javascript
运行
复制
?- same([josh,muse], [sam,muse]).
true.

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

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

最后要注意的是,你的问题是关于术语相等的,但在你的解决方案中,你使用的是术语统一。它们具有不同的语义,不应混淆。

票数 1
EN

Stack Overflow用户

发布于 2018-11-23 05:19:48

在阅读你的问题时,你首先给出了一个事实数据库

代码语言:javascript
运行
复制
likes(josh,muse).
likes(sam,muse).
likes(josh,gnr).
likes(sam, radiohead).

但随后使用list作为谓词

代码语言:javascript
运行
复制
same([josh,muse], [sam,muse]).

正如保罗从列表开始回答的那样,我将从事实开始回答。

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

代码语言:javascript
运行
复制
same_1(P1,P2,Item) :-
    likes(P1,Item),
    likes(P2,Item).

这给了我们

代码语言:javascript
运行
复制
?- 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。

代码语言:javascript
运行
复制
same_2(P1,P2,Item) :-
    likes(P1,Item),
    likes(P2,Item),
    P1 \= P2.

这给了我们

代码语言:javascript
运行
复制
?- same_2(P1,P2,Item).
P1 = josh,
P2 = sam,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
false.

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

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

代码语言:javascript
运行
复制
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.

它会返回

代码语言:javascript
运行
复制
?- same_3(P1,P2,Item).
P1 = sam,
P2 = josh,
Item = muse ;
P1 = sam,
P2 = josh,
Item = muse ;
false.

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

现在只保存生成的结果,并且只向结果中添加唯一项。这是使用setof/3完成的。

代码语言:javascript
运行
复制
?- setof((P1,P2,Item),(same_3(P1,P2,Item)),Bag).
Bag = [(sam, josh, muse)].
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53437271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档