1
votes

Using SWI-Prolog's listing predicate (or SICStus' predicate in its list library), we have:

lists:subtract([], _, []) :- !.
lists:subtract([A|C], B, D) :-
    memberchk(A, B), !,
    subtract(C, B, D).
lists:subtract([A|B], C, [A|D]) :-
    subtract(B, C, D).

which does this successfully:

?- subtract([2,3,4,5],[3,4],X).
X = [2, 5].

BUT, what if I want to do:

?- new_subtract([2,3,4,5],[3,X],Y).
X = [3, 2],
X = [3, 4],
X = [3, 5],

Y then has three solutions by taking the three X solutions from [2,3,4,5].

However, subtract/2 doesn't allow for this.

I've been trying to solve this for ages by taking the cuts (!)s out of the built in predicate's body to try and get it to backtrack and find all the solutions.

1

1 Answers

4
votes

I assume you mean

?- new_subtract([2,3,4,5],[3,X],Y).
Y = [3, 2] ;
Y = [3, 4] ;
Y = [3, 5]

The following definition does that, but does not preserve all of subtract/3's behavior:

sub(List,[],List).
sub(List,[X|Sub],Rem) :- select(X,List,Rem0), sub(Rem0,Sub,Rem).

Usage:

?- sub([2,3,4,5],[3,X],Y).
X = 2,
Y = [4, 5] ;
X = 4,
Y = [2, 5] ;
X = 5,
Y = [2, 4] ;
false.