1

我有一个包含以下规则的数据库;

speaks(fred [german, english, dutch]).
speaks(mary [spanish, arabic, dutch]).
speaks(jim [norwegian, italian, english]).
speaks(sam [polish, swedish, danish]).

ETC

作为一个更大的项目的一部分,我如何找出 3 个说同一种语言的人?

4

2 回答 2

3

事实上,Franz 的解决方案将不起作用:它返回讲相同语言的三元组 prople,但这些三元组可能包含重复项。因此,人们仍然不得不求助于例如sort/2length/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并成功。如果列表包含不同的人,则成功,所有这些人都会说语言。该谓词使用; 如果谓词的定义包含重复数据,则应改为使用。LSsame_language/3SSNLbagof/3speak/2setof/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.
于 2009-11-22T17:11:24.237 回答
0

已经有一段时间了,所以可能会有一些语法故障,但我希望你明白......

% 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).

注意:这些命令将为您提供三人组的所有可能组合,因此如果您有四个说英语的人,第一个命令将为您提供四个结果集。

于 2009-11-22T16:11:52.027 回答