让我们说Prolog中有一个简单的人员数据库
person(john).
person(mary).
person(john).
person(susan).
我需要恰好匹配entires一次:
john-mary, john-john, john-susan, mary-john, mary-susan, john-susan
我尝试过这样的事情:
match:- person(X),!,person(Y), write(X),write(-), write(Y),nl.
run:- person(X), match(X), fail.
但它匹配了很多次,并且将一个人与他/她相匹配,这不应该是。
基本上,我需要的是迭代所有X并让Prolog严格看待"低于"对于Ys。
答案 0 :(得分:2)
快速解决方案是为您的员工编号:
person(1, john).
person(2, mary).
person(3, john).
person(4, susan).
然后你可以匹配这样的人:
match(X-Y) :-
person(I, X), person(J, Y), I < J.
由于您有两个john
条目,我不确定任何其他解决方案是否可行。通常你可以使用@>/2
伪造一个排序,但这需要你的原子是唯一的,因为它们不是,它会阻止john-john
解决方案。
修改:由于我们愿意使用findall/3
来实现人员数据库,因此我们可以将其视为列表问题并找到功能性解决方案。让我们在列表中获得所有组合:
combinations([X|Rest], X, Y) :- member(Y, Rest).
combinations([_|Rest], X, Y) :- combinations(Rest, X, Y).
有了这个谓词,我们可以找到解决方案:
combined_folks(People) :-
findall(P, person(P), Persons),
findall(X-Y, combinations(Persons, X, Y), People).
?- combined_folks(X).
X = [john-mary, john-john, john-susan, mary-john, mary-susan, john-susan].
实际上结果很干净!
答案 1 :(得分:1)
person(john).
person(mary).
person(john).
person(susan).
match :- findall(P,person(P),People), match_all(People).
match_all([_]) :- !.
match_all([P|People]) :- match_2(P,People), match_all(People).
match_2(_,[]) :- !.
match_2(P1,[P2|People]) :- format('~a-~a~n',[P1,P2]), match_2(P1,People).
?- match.