我有一个包含以下规则的数据库;
speaks(fred [german, english, dutch]).
speaks(mary [spanish, arabic, dutch]).
speaks(jim [norwegian, italian, english]).
speaks(sam [polish, swedish, danish]).
ETC
作为一个更大的项目的一部分,我如何找出 3 个说同一种语言的人?
仁
事实上,Franz 的解决方案将不起作用:它返回讲相同语言的三元组 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
请注意,这很好地概括了问题:我们现在可以回答任何 n的问题,而不仅仅是 3。演示:
?- same_language(3, L, SS).
false.
?- same_language(2, L, SS).
L = dutch,
SS = [fred, mary] ;
L = english,
SS = [fred, jim] ;
false.
已经有一段时间了,所以可能会有一些语法故障,但我希望你明白......
% 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).
注意:这些命令将为您提供三人组的所有可能组合,因此如果您有四个说英语的人,第一个命令将为您提供四个结果集。