我有一个由以下规则组成的数据库;序言列表问题
speaks(fred [german, english, dutch]).
speaks(mary [spanish, arabic, dutch]).
speaks(jim [norwegian, italian, english]).
speaks(sam [polish, swedish, danish]).
等
作为一个更大的计划的一部分,我怎么会发现3人谁讲同一种语言?
仁
我有一个由以下规则组成的数据库;序言列表问题
speaks(fred [german, english, dutch]).
speaks(mary [spanish, arabic, dutch]).
speaks(jim [norwegian, italian, english]).
speaks(sam [polish, swedish, danish]).
等
作为一个更大的计划的一部分,我怎么会发现3人谁讲同一种语言?
仁
它已经有一段时间,所以可能有一些语法毛刺,但我希望你的想法...
% Find out whether an element is contained in a list
in_list(X,[X|_]).
in_list(X,[First|Rest]) :- in_list(X,Rest).
% Find out 3 people who speak the same language
findspeakers(Language, X1, X2, X3) :- speaks(X1, L1), speaks(X2, L2), speaks(X3, L3), in_list(Language, L1), in_list(Language, L2), in_list(Language, L3).
很简单使用的解决方案列表操作(我没有记住是否有一个内置的规则来确定一个变量是否包含在列表中,所以我重写了它)。
你可以找到的三个人用下面的命令说英语组:
findspeakers('English', X1, X2, X3).
你可以找到的三个人全部群体来讲的共同语言使用以下命令:
findspeakers(Language, X1, X2, X3).
注意:这些命令会给你三人一组的所有可能的组合,所以如果你有四个人说英语,第一个命令会为您提供四个结果集。
正因为如此,Franz' solution将无法正常工作:它将返回讲同一种语言prople的三倍,但这些三元可能包含重复。因此,人们仍然必须诉诸于例如sort/2
和length/2
找到了答案,原来的问题:
?- findspeakers(Language, X1, X2, X3), sort([X1, X2, X3], Y), length(Y, 3).
false.
(因此,答案是没有,有没有三个人说同一种语言。)无论如何,我认为一个更优雅的解决方案存在:
spoken(L, S) :-
speaks(S, LL), member(L, LL).
same_language(N, L, SS) :-
bagof(S, spoken(L, S), SS), length(SS, N).
谓词spoken/2
使用member/2
如果语言L
被人S
讲成功。 same_language/3
成功如果列表SS
包含N
不同的人,所有这些都讲的语言L
。这个谓词使用bagof/3
;如果speak/2
谓词的定义包含重复数据,则应该使用setof/3
代替。
观察,这很好的可以推广的问题:我们现在可以回答任何ñ的问题,而不仅仅是3.示范:
?- same_language(3, L, SS).
false.
?- same_language(2, L, SS).
L = dutch,
SS = [fred, mary] ;
L = english,
SS = [fred, jim] ;
false.
它不应该是'讲(弗雷德,[德,英语,荷兰语])。(注意额外的逗号)? 另外:这功课?如果是这样,请将其标记为家庭作业。 – Franz 2009-11-22 15:34:41
它确实有一点家常气味。 – nedned 2009-11-24 14:21:23