我有学生和他们做运动的预测,我想知道哪些学生做了特定的运动。到目前为止,我有这样的结果,但只有在列表中输入精确的运动,而我的查找谓词只能在列表中找到一项运动时,我才能得到结果。我不知道如何把它组合起来,用它来找到做运动的学生:
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).我试过这样的方法:
?- does_sport(X, find(soccer, L)).这只是返回假。我知道我需要将我的体育列表链接到does_sports谓词,但不确定如何链接。
(如有任何意见,欢迎:)
发布于 2017-05-28 14:40:35
要了解哪些学生从事某项特定运动,您可以定义如下谓词:
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然后,您可以查询例如足球,就像您在问题中所打算的那样:
?- student_sport(St,soccer).
St = 'Quintin Tarentino' ? ;
no另一方面,曲棍球产生了两个结果:
?- student_sport(St,hockey).
St = 'Quintin Tarentino' ? ;
St = 'Ed Harris' ? ;
no如果您想要一张学生的曲棍球清单,您可以使用findall/3,如下所示:
?- findall(St,student_sport(St,hockey),L).
L = ['Quintin Tarentino','Ed Harris']或者选择setof/3获取排序列表(如果您碰巧有包含任何内容的事实,则不要重复):
?- 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/3和setof/3中添加了示例查询,以展示如何在列表中收集解决方案。您可以很容易地定义一个谓词students_sport/2,它描述一项特定运动与所有练习该运动的学生之间的关系:
students_sport(L,Sp) :-
setof(St,student_sport(St,Sp),L).关于体育运动,您可以选择一个原子来表示这种情况,比如none,然后向student_sport/2添加一个相应的规则,如下所示:
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).这将产生以下结果:
?- 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)).表明您似乎期望某种类型的返回值。您可以将谓词视为返回true或false的函数,但在编写Prolog程序时通常不太有用。参数find(soccer,L)并不像您所期望的那样被调用,而是作为一个参数来传递。既然你的事实不包括
does_sport(*SomeStudentHere*, find(soccer,L)).查询失败。
https://stackoverflow.com/questions/44226757
复制相似问题