首页 > 解决方案 > 两个变量的Prolog回溯findall

问题描述

我想写一个函数resident(Housenumber,N)

(1) 在给定门牌号的情况下,给我每所房子的居民数量

(2) 当 Housenumber 是一个变量时,可以回溯每个门牌号的所有居民数量。

以居民的形式给出以下事实(名字,姓氏,门牌号)。

resident('Tim','Cook',1).
resident('Elisabeth','Cook',1).
resident('Thomas','Cook',1).
resident('George','Cook',1).
resident('Steve','Jobs',2).
resident('Lisa','Jobs',2).
resident('Karen','Jobs',2).
resident('Mark','Zuckerberg',3).
resident('Priscilla','Zuckerberg',3).

第二个条件应该像这样工作:

residents(X,N).
X = 1,
N = 4,
X = 2,
N = 3,
X = 3,
N = 2.

我尝试了以下尝试。

residents(X,N):-
findall(X,resident(_,_,X),L),
length(L,N).

第一个条件是满足的,但是,第二个条件给了我所有居民的总数,而不是为每所房子聚集。我也尝试了 bagof 和 setof 谓词,但没有帮助。非常感谢您的帮助。

标签: prolog

解决方案


问题是findall/3自动量化自由变量(这里的名字和姓氏),以便合并同一地址的所有解决方案。看一下bagof/3(参见例如 SWI 文档),它允许您手动量化(这里没有必要)。要查找居住在该地址的人数,列表L还需要收集每个号码的居民姓名,而不是号码本身:

?- bagof(X-Y, resident(X,Y,Z), Zs), length(Zs, N).
Z = 1,
Zs = ['Tim'-'Cook', 'Elisabeth'-'Cook', 'Thomas'-'Cook', 'George'-'Cook'],
N = 4 ;
Z = 2,
Zs = ['Steve'-'Jobs', 'Lisa'-'Jobs', 'Karen'-'Jobs'],
N = 3 ;
Z = 3,
Zs = ['Mark'-'Zuckerberg', 'Priscilla'-'Zuckerberg'],
N = 2.

推荐阅读