首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Prolog -在谓词中搜索列表

Prolog -在谓词中搜索列表
EN

Stack Overflow用户
提问于 2017-05-28 11:24:19
回答 1查看 973关注 0票数 1

我有学生和他们做运动的预测,我想知道哪些学生做了特定的运动。到目前为止,我有这样的结果,但只有在列表中输入精确的运动,而我的查找谓词只能在列表中找到一项运动时,我才能得到结果。我不知道如何把它组合起来,用它来找到做运动的学生:

代码语言:javascript
复制
student('Quinton Tarentino', male, 12).
student('Tom Hanks', male, 9).
student('Ed Harris', male, 11).

does_sport('Quinton Tarentino', [soccer, hockey, cricket]).
does_sport('Tom Hanks', []).
does_sport('Ed Harris', [hockey, swimming]).

sports([soccer, hockey, swimming, cricket, netball]).

find(X) :- sports(L), member(X, L).

我试过这样的方法:

代码语言:javascript
复制
?- does_sport(X, find(soccer, L)).

这只是返回假。我知道我需要将我的体育列表链接到does_sports谓词,但不确定如何链接。

(如有任何意见,欢迎:)

EN

回答 1

Stack Overflow用户

发布于 2017-05-28 14:40:35

要了解哪些学生从事某项特定运动,您可以定义如下谓词:

代码语言:javascript
复制
student_sport(St,Sp) :-
   does_sport(St,L),      % L is a list of sports student St does
   member(Sp,L).          % Sp is a member of list L

然后,您可以查询例如足球,就像您在问题中所打算的那样:

代码语言:javascript
复制
   ?- student_sport(St,soccer).
St = 'Quintin Tarentino' ? ;
no

另一方面,曲棍球产生了两个结果:

代码语言:javascript
复制
   ?- student_sport(St,hockey).
St = 'Quintin Tarentino' ? ;
St = 'Ed Harris' ? ;
no

如果您想要一张学生的曲棍球清单,您可以使用findall/3,如下所示:

代码语言:javascript
复制
   ?- findall(St,student_sport(St,hockey),L).
L = ['Quintin Tarentino','Ed Harris']

或者选择setof/3获取排序列表(如果您碰巧有包含任何内容的事实,则不要重复):

代码语言:javascript
复制
   ?- setof(St,student_sport(St,hockey),L).
L = ['Ed Harris','Quintin Tarentino']

请注意,在某些Prolog中,您可能必须显式地包含一个库才能使用member/2,例如在Yap::- use_module(library(lists)).中,而另一些则需要自动加载它,例如SWI。

编辑:

关于您在评论中提出的问题,让我们从您的观察开始,即student_sport/2一次只生成一个答案。这是有意的,就像包含单数的学生这个词的谓词名称所暗示的那样:它描述了学生与特定运动之间的关系,而这正是学生所实践的。这就是为什么我在findall/3setof/3中添加了示例查询,以展示如何在列表中收集解决方案。您可以很容易地定义一个谓词students_sport/2,它描述一项特定运动与所有练习该运动的学生之间的关系:

代码语言:javascript
复制
students_sport(L,Sp) :-
   setof(St,student_sport(St,Sp),L).

关于体育运动,您可以选择一个原子来表示这种情况,比如none,然后向student_sport/2添加一个相应的规则,如下所示:

代码语言:javascript
复制
student_sport(St,none) :-   % <- rule for the sports-austere
   does_sport(St,[]).       % <- succeeds if the student does no sport
student_sport(St,Sp) :-
   does_sport(St,L),
   member(Sp,L).

这将产生以下结果:

代码语言:javascript
复制
   ?- student_sport(St,none).
St = 'Tom Hanks' ? ;
no

   ?- students_sport(St,none).
St = ['Tom Hanks']

   ?- students_sport(St,hockey).
St = ['Ed Harris','Quintin Tarentino']

   ?- students_sport(St,Sp).
Sp = cricket,
St = ['Quintin Tarentino'] ? ;
Sp = hockey,
St = ['Ed Harris','Quintin Tarentino'] ? ;
Sp = none,
St = ['Tom Hanks'] ? ;
Sp = soccer,
St = ['Quintin Tarentino'] ? ;
Sp = swimming,
St = ['Ed Harris']

最后,关于您的代码与我编写的代码完全相同的假设:结构上有一个相似之处,即谓词find/1有一个涉及列表的第一个目标(sports/1),然后使用member/2检查该列表中的成员身份。student_sport/2的第二个规则(或编辑前的单个规则)也有一个涉及列表的第一个目标(但另一个目标是:does_sport/2),随后使用member/2检查该列表中的成员资格。相似之处到此为止。我提供的版本根本不是使用sports/1,而是does_sport/2中与特定学生相关的运动列表。请注意,find/1并不描述与学生的任何连接。此外,您的查询?- does_sport(X, find(soccer, L)).表明您似乎期望某种类型的返回值。您可以将谓词视为返回truefalse的函数,但在编写Prolog程序时通常不太有用。参数find(soccer,L)并不像您所期望的那样被调用,而是作为一个参数来传递。既然你的事实不包括

代码语言:javascript
复制
does_sport(*SomeStudentHere*, find(soccer,L)).

查询失败。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44226757

复制
相关文章

相似问题

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