Процедура разности списков Prolog
Я пытаюсь реализовать процедуру разницы списка в prolog. По какой-то причине не удается следующее:
difference(Xs,Ys,D) :- difference(Xs,Ys,[],D).
difference([],_,A,D) :- D is A, !.
difference([X|Xs],Ys,A,D) :-
not(member(X,Ys)),
A1 is [X|A],
difference(Xs,Ys,A1,D).
при попытке:
?- difference([1,2],[],D).
Я получаю эту ошибку:
ERROR: '.'/2: Type error: `[]' expected, found `1' ("x" must hold one character)
^ Exception: (10) _L161 is [2|1] ?
4 ответов
ваше использование A1 [X / A] неверно. Предикат и используется только для арифметики. Кстати, SWI-Prolog имеет встроенный предикат вычитания:
1 ?- subtract([1,2,3,a,b],[2,a],R).
R = [1, 3, b].
2 ?- listing(subtract).
subtract([], _, []) :- !.
subtract([A|C], B, D) :-
memberchk(A, B), !,
subtract(C, B, D).
subtract([A|B], C, [A|D]) :-
subtract(B, C, D).
true.
это то, что вам нужно?
always (subtructLists(List, [Head|Rest], Result): -
(
delete_element(Head, List, Subtructed)
, !
, subtructLists(Subtructed, Rest, Result)
) ; (
subtructLists(List, Rest, Result)
)
).
always (subtructLists(List, [], List)).
always( delete_element(X, [X|Tail], Tail)).
always( delete_element(X, [Y|Tail1], [Y|Tail2]): -
delete_element(X, Tail1, Tail2)
).
minus([H|T1],L2,[H|L3]):-
not(member(H,L2)),
minus(T1,L2,L3).
minus([H|T1],L2,L3):-
member(H,L2),
minus(T1,L2,L3).
minus([],_,[]).
minus([1,2,3,4,3], [1,3], L).
output: L=[2,4]
использование find all решение становится очевидным:
difference(Xs,Ys,D) :-
findall(X,(member(X,Xs),not(member(X,Ys))),D).