Answer with (=)/3
list_uniqs_alldups(Es,Us,Ds) : tpartition(list_uniqmember_t(Es),Es,Us,Ds). list_uniqmember_t(Es,X,T) :- tfilter(=(X),Es,Xs), =(Xs,[X],T).
Request examples:
?- list_uniqs_alldups([1,1,2,1,1,3,4,3],Us,Ds). Us = [2, 4], Ds = [1, 1, 1, 1, 3, 3]. ?- list_uniqs_alldups([1,1,2,3,3,1,1,3,4,3],Us,Ds). Us = [2, 4], Ds = [1, 1, 3, 3, 1, 1, 3, 3]. ?- list_uniqs_alldups([8,1,1,2,3,3,1,1,3,4,3],Us,Ds). Us = [8, 2, 4], Ds = [1, 1, 3, 3, 1, 1, 3, 3]. ?- list_uniqs_alldups(X,Us,Ds). X = Us, Us = Ds, Ds = [] ; X = Us, Us = [_A], Ds = [] ; X = Ds, Us = [], Ds = [_A,_A] ; X = Ds, Us = [], Ds = [_A,_A,_A] ; ...
To encode the length of the path, I used splitlistIfAdj/3 .
list_rle(List,Rle) :- splitlistIfAdj(dif,List,Rle0), maplist(rle_length,Rle0,Rle). rle_length([H|T],RleLen) :- length([H|T],L), RleLen = L*H.
Query:
?- list_rle([a,a,b,a,a,c,d,c],X). X = [2*a, 1*b, 2*a, 1*c, 1*d, 1*c].
I'm not sure how to change this so that it works in both directions.
Then you can also:
new_list_uniqs_alldups(List,Us,Ds):- list_rle(List,Rle), tpartition(singlelist_t,Rle,Us,Ds). singlelist_t(L,T) :- L=N*_, if_(N=1,T=true,T=false).
Example Q:
?- new_list_uniqs_alldups([1,1,2,1,1,3,4,1,1,7,8],U,D). U = [1*2, 1*3, 1*4, 1*7, 1*8], D = [2*1, 2*1, 2*1]. ?- new_list_uniqs_alldups([7,7,7,2,1,1,3,4,1,1,7,8],U,D). U = [1*2, 1*3, 1*4, 1*7, 1*8], D = [3*7, 2*1, 2*1].