【问题标题】:Match database items exactly once in Prolog?在 Prolog 中只匹配一次数据库项目?
【发布时间】:2013-02-25 19:56:08
【问题描述】:

假设 Prolog 中有一个简单的人员数据库

person(john).
person(mary).    
person(john).
person(susan).

我需要完全匹配一次:

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 严格地在 Y 的“下方”查看。

【问题讨论】:

    标签: prolog


    【解决方案1】:

    一个快速的解决方案是给你的人编号:

    person(1, john).
    person(2, mary).
    person(3, john).
    person(4, susan).
    

    那么你可以像这样匹配人:

    match(X-Y) :-
      person(I, X), person(J, Y), I < J.
    

    由于您有两个 john 条目,我不确定任何其他解决方案是否会起作用。通常你可以使用@&gt;/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].
    

    结果其实很干净!

    【讨论】:

    • 这是一条出路,但我不能对原始数据库进行任何更改。有没有办法生成具有唯一编号的新数据库?
    • 我相信这是可能的,但在这一点上,只写一些可以给你列表排列的东西并使用bagof/3 来获取所有人并将它们作为列表。
    • 我为此使用了 findall/3。现在,当我有一个列表时,我该如何解决这个问题?
    • 遍历列表;从头开始,仅将每个元素与列表中它之后的元素匹配。
    • 我不能不理会这个问题。 :)
    【解决方案2】:
    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.
    

    【讨论】:

    • 也许第一行不应该有“_”?
    • 第二行的最后一个子目标应该是 match_all(People)。然后一切正常!谢谢!
    • 递归子句末尾的_没问题,最后一个目标确实没了。
    猜你喜欢
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多