我刚刚开始使用Prolog,所以我不太明白。我有事实:
circle(сhess, abbot).
circle(сhess, hannigan).
circle(сhess, abrams).
circle(crystal_voice, blake).
circle(crystal_voice, weller).
circle(crystal_voice, huxley).
circle(local_studies, barnes).
circle(local_studies, haskins).
circle(local_studies, abrams).
circle(local_studies, aberdeen).
circle(art, barnes).
circle(art, abbot).
circle(art, blake).
person(abbot, male, 20).
person(aberdeen, female, 18).
person(weller, male, 22).
person(abrams, female, 25).
person(adams, male, 21).
person(bond, female, 12).
person(haskins, male, 15).
person(blake, female, 20).
person(barnes, male, 20).
person(hannigan, female, 15).
person(huxley, male, 18).我需要解决这个问题:找一份参与多个圈子的人的名单。
我有一个代码,它只找到一个人访问的圆圈的数目。
count(Name, Count):-
findall(1, circle(_, Name), List),
length(List, Count). 发布于 2022-11-15 18:18:15
初学者的方法是:
circles2(Person) :-
circle(Circle1, Person),
dif(Circle1, Circle2),
circle(Circle2, Person).
circles2_people(People) :-
setof(Person, circles2(Person), People)...。这产生了正确的答案:
?- circles2_people(People).
People = [abbot, abrams, barnes, blake]...。但是,由于circles2生成重复项,setof随后删除了这些副本,所以效率有点低:
?- bagof(Person, circles2(Person), People).
People = [abbot, abrams, blake, barnes, abrams, barnes, abbot, blake].因此,可以用作优化:
person_circles2(Person) :-
person(Person, _, _),
once(circles2(Person)).上面的代码“循环”通过人员(由于回溯),并且至多为每个人尝试一次以满足circles2约束-这并不是重复人员的:
?- bagof(Person, person_circles2(Person), People).
People = [abbot, abrams, blake, barnes].但是,通常仍将使用setof而不是bagof,这样优化的好处也是为了明确意图:
?- setof(Person, person_circles2(Person), People).
People = [abbot, abrams, barnes, blake].发布于 2022-11-15 20:51:45
定义第一种情况(找到一个在一个以上圈内的人)很容易:
person_in_multiple_circles(P) :-
person(P,_,_),
circle(C1,P),
circle(C2,P),
C1 \= C2
.然而,这会给你带来重复的结果。
你可以和setof/3一起赢
persons_in_multiple_circles(Ps) :-
setof( P, person_in_multiple_circles(P) , Ps )
.但是,使用append/3和memberchk/2可能更容易,可以这样说:
persons_in_multiple_circles(Ps) :- % To find the list of all persons in multiple circles, ...
findall( P , circle(_,P) , P0 ), % - find all persons in at least one circle, and
findall( D , is_duplicate(P0,D) , Ps ) % - find all duplicates in that list
.
is_duplicate( Xs , X ) :- % X is duplicated in Xs, if...
append(_,[X|X1],Xs), % - X is found in Xs, and
memberchk(X,X1) . % - X can be found further along in Xshttps://stackoverflow.com/questions/74450004
复制相似问题