首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >找出参加一个以上圈子的人的名单。

找出参加一个以上圈子的人的名单。
EN

Stack Overflow用户
提问于 2022-11-15 17:40:38
回答 2查看 38关注 0票数 0

我刚刚开始使用Prolog,所以我不太明白。我有事实:

代码语言:javascript
复制
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).

我需要解决这个问题:找一份参与多个圈子的人的名单。

我有一个代码,它只找到一个人访问的圆圈的数目。

代码语言:javascript
复制
count(Name, Count):- 
   findall(1, circle(_, Name), List),
   length(List, Count). 
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-15 18:18:15

初学者的方法是:

代码语言:javascript
复制
circles2(Person) :-
    circle(Circle1, Person),
    dif(Circle1, Circle2),
    circle(Circle2, Person).
    
circles2_people(People) :-
    setof(Person, circles2(Person), People).

..。这产生了正确的答案:

代码语言:javascript
复制
?- circles2_people(People).
People = [abbot, abrams, barnes, blake].

..。但是,由于circles2生成重复项,setof随后删除了这些副本,所以效率有点低:

代码语言:javascript
复制
?- bagof(Person, circles2(Person), People).
People = [abbot, abrams, blake, barnes, abrams, barnes, abbot, blake].

因此,可以用作优化:

代码语言:javascript
复制
person_circles2(Person) :-
    person(Person, _, _),
    once(circles2(Person)).

上面的代码“循环”通过人员(由于回溯),并且至多为每个人尝试一次以满足circles2约束-这并不是重复人员的

代码语言:javascript
复制
?- bagof(Person, person_circles2(Person), People).
People = [abbot, abrams, blake, barnes].

但是,通常仍将使用setof而不是bagof,这样优化的好处也是为了明确意图:

代码语言:javascript
复制
?- setof(Person, person_circles2(Person), People).
People = [abbot, abrams, barnes, blake].
票数 0
EN

Stack Overflow用户

发布于 2022-11-15 20:51:45

定义第一种情况(找到一个在一个以上圈内的人)很容易:

代码语言:javascript
复制
person_in_multiple_circles(P) :-
    person(P,_,_),
    circle(C1,P),
    circle(C2,P),
    C1 \= C2
    .

然而,这会给你带来重复的结果。

你可以和setof/3一起赢

代码语言:javascript
复制
persons_in_multiple_circles(Ps) :-
  setof( P, person_in_multiple_circles(P) , Ps )
  .

但是,使用append/3memberchk/2可能更容易,可以这样说:

代码语言:javascript
复制
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 Xs
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74450004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档