Prolog removing unique elements only

Prolog rules are read independently of each other, so you need one rule for the case where the element is unique and one where it is not. Provided the order of the elements is not relevant, you might use:

?- remUniqueVals([A,B,C], [1,1]).
A = B, B = 1,
dif(C, 1) ;
A = C, C = 1,
dif(B, 1),
dif(B, 1) ;
B = C, C = 1,
dif(A, 1),
dif(A, 1) ;
false.

?- remUniqueVals([1,1,2,2,3,4,4,5,6,6,6],Q).
Q = [1, 1, 2, 2, 4, 4, 6, 6, 6] ;
false.

remUniqueVals([], []).
remUniqueVals([Q1|RestQ],[Q1|Xs0]) :-
   memberd(Q1, RestQ),
   phrase(delall(Q1, RestQ, NewQ), Xs0, Xs),
   remUniqueVals(NewQ, Xs).
remUniqueVals([Q1|RestQ],Xs) :-
   maplist(dif(Q1), RestQ),
   remUniqueVals(RestQ,Xs).

memberd(X, [X|_Xs]).
memberd(X, [Y|Xs]) :-
   dif(X,Y),
   memberd(X, Xs).

delall(_X, [], []) --> [].
delall(X, [X|Xs], Ys) -->
   [X],
   delall(X, Xs, Ys).
delall(X, [Y|Xs], [Y|Ys]) -->
   {dif(X,Y)},
   delall(X, Xs, Ys).

Here is an alternate definition for memberd/2 which might be more efficient using if_/3:

memberd(E, [X|Xs]) :-
   if_(E = X, true, memberd(E, Xs) ).

Leave a Comment