因此,我需要创建一个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]
因为它只返回在列表中出现一次的值。我要执行的操作的问题在于,我无法将member
或delete
谓词与“-”构造函数一起使用。基本上,我必须先将每个项目分为两部分,然后再比较变量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]
。我怎样才能做到这一点?
答案 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无关...