1

我需要在 prolog 中实现字典配对。这就是我所做的:

pp((A, B), (B,C), RES) :-
    RES = [(A,C)].

pp((A, AA),[B|BS], RES) :-
    pp((A, AA), B, RES1),
    pp((A, AA), BS, RES2),
    append(RES1, RES2, RES).

pp([A|AS], [B|BS], C) :-
    pp(A, [B|BS], RES1),
    pp(AS, [B|BS], RES2),
    append(RES1, RES2, RES),
    list_to_set(RES, C).
pp(_, _, C) :-
    C = [].

输出:

?- pp([(a,b),(b,c)],[(b,c),(c,z)],C).
C = [ (a, c), (b, z)] ;
C = [ (a, c)] ;
C = [ (a, c)] ;
C = [ (a, c)] ;
C = [ (a, c)] ;
C = [ (a, c), (b, z)] ;
C = [ (a, c)] ;
C = [ (a, c)] ;
C = [ (a, c)] ;
C = [ (a, c)] ;
C = [ (b, z)] ;
C = [] ;
C = [] ;
C = [] ;
C = [] ;
C = [ (b, z)] ;
C = [] ;
C = [] ;
C = [] ;
C = [] ;
C = [ (b, z)] ;
C = [] ;
C = [] ;
C = [] ;
C = [] ;
C = [].

?- 

第一个结果是正确的答案。问题是为什么谓词 pp 允许 C 是所有其他值?

4

1 回答 1

1

Prolog 将尝试它可以匹配的所有替代方案,然后您将这些结果作为算法中进行的意外计算的结果。

您正在“重载” pp/3,使用它来匹配列表元素。这没什么意义,因为您的数据结构不是递归的。

我认为您可以使用一些内置的,比 list_to_set/2 更容易应用的,而不是建议进行削减(削减提交到已完成的选择,然后可以帮助避免这种虚假的结果)

pp([],_,[]).
pp([(A,B)|As], X, [(A,C)|R]) :- select((B,C), X, Y), !, pp(As, Y, R).
% BUG ! pp([_|As], X, R) :- select(As, X, R).
pp([_|As], X, R) :- pp(As, X, R).

请注意成功选择/ 3 后的剪切,避免出现“跳过规则”。

编辑以从第二个字典中获取更多单词,让我们重试成功匹配:

pp([(A,B)|As], X, [(A,C)|R]) :- select((B,C), X, Y), !, pp([(A,B)|As], Y, R).
于 2013-10-10T12:45:44.620 回答