如何在Prolog中使用“-”构造函数?

时间:2019-03-14 04:27:29

标签: prolog

因此,我需要创建一个Prolog谓词,该谓词需要一个看起来像[true-X, false-Y, false-X, true-Z]的输入,并且只返回出现一次的变量。因此,对于此示例,由于Z仅出现一次,它将返回[true-Z]。我已经能够使用普通列表做到这一点。

singles([],[]).

singles([H | T], L) :-    
     member(H, T), 
     delete(T, H, Y),
     singles( Y, L).

singles([H | T], [H|T1]) :- 
      \+member(H, T),
      singles(T, T1).

如果我运行它,它将返回

?- singles([1,1,2,3,4,3,3,2], R).
R = [4]

因为它只返回在列表中出现一次的值。我要执行的操作的问题在于,我无法将memberdelete谓词与“-”构造函数一起使用。基本上,我必须先将每个项目分为两部分,然后再比较变量singles([Pol-Var | T], L)。为了比较这两个变量,我创建了一个occurs谓词,用于比较列表开头的变量。

occurs(X, [Pol-Var|T]) :- X == Var.

这是我到目前为止所拥有的。

singles([],[]).

singles([Pol-Var | T], L) :- 
     occurs(Var, T),
     singles(T, L).

singles([Pol-Var | T], [Pol-Var|T1]) :- 
      \+occurs(Var, T),
      singles(T, T1).

occurs(X, [Pol-Var|T]) :- X == Var.

这基本上就像如果我有输入[1,1,2,3,2],那么输出将是[1,2,3,2],因此它只是删除彼此相邻的所有重复项。因此,如果我有输入[true-X, false-X, false-Y, true-Y, true-Z],那么输出将是[false-X, true-Y, true-Z],而我希望它是[true-Z]。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:3)

正如Daniel在他的第一条评论中指出的那样,您面临的真正问题是Prolog在诸如member / 2或delete / 3之类的内置参数之间进行了不必要的统一。 Prolog社区的旧trick-of-the-trade是使用双重否定来实现匹配的而没有统一,但是正如我们将看到的那样,这对您没有太大帮助

解决问题的更简单方法似乎是重写member / 2和delete / 3,所以可能是:

singles([],[]).

singles([H | T], L) :-
     member_(H, T),
     delete_(T, H, Y),
     singles(Y, L).

singles([H | T], [H | T1]) :-
      \+member_(H, T),
      singles(T, T1).

member_(_-H, [_-T|_]) :- H == T, !.
member_(E, [_|R]) :- member_(E, R).

delete_([], _, []).
delete_([_-T|Ts], F-H, Rs) :- T == H, !, delete_(Ts, F-H, Rs).
delete_([T|Ts], H, [T|Rs]) :- delete_(Ts, H, Rs).

可以产生

?- singles([true-X, false-Y, false-X, true-Z],S).
S = [false-Y, true-Z]

您可能会发现自己对要求的要求不足:从您的测试用例看来,我们应该删除每次出现的false-VAR,而与VAR无关...