I’m trying to implement a distinct/2 predicate, that takes two lists A and B where B has the same elements as A without duplicates (ordering is preserved).
some examples:
distinct([1,2,2,3],[1,2,3]).
distinct([3,2,3,1,2,3],[3,2,1]).
Here is my code
not_member(_,[]).
not_member(X,[Y|Z]) :-
dif(X,Y),
not_member(X,Z).
distinct([],[]).
distinct(A,B) :-
length(A,LA),
length(B,LB),
LA #>= LB,
distinct_(A,B,[]).
distinct_([],B,Seen) :-
reverse(B,Seen).
distinct_([X|A],B,Seen) :-
member(X,Seen),
distinct_(A,B,Seen).
distinct_([X|A],B,Seen) :-
not_member(X,Seen),
distinct_(A,B,[X|Seen]).
% ?- distinct([1,2,2,3,2],X).
%@ X = [1, 2, 3] ;
% DO NOT TERMINATE
% ?- distinct(X,[1,2,3]).
%@ X = [1, 2, 3] ;
%@ X = [1, 1, 2, 3] ;
%@ X = [1, 2, 2, 3] ;
%@ X = [1, 2, 1, 3] ;
%@ X = [1, 2, 3, 3] ;
%@ X = [1, 2, 3, 2] ;
%@ X = [1, 2, 3, 1] ;
%@ X = [1, 1, 1, 2, 3] ;
%@ X = [1, 1, 2, 2, 3] ...
% ?- length(X,3), length(Y,2), distinct(X,Y).
%@ X = [_A, _A, _B],
%@ Y = [_A, _B],
%@ dif(_B, _A) ;
%@ X = [_A, _B, _B],
%@ Y = [_A, _B],
%@ dif(_B, _A) ;
%@ X = [_A, _B, _A],
%@ Y = [_A, _B],
%@ dif(_B, _A) ;
%@ false.
I’m trying to understand why the first query do not terminate.
I am also open to learn about a better way to implement such relation.
Thank you