I want to count one element in the list and stop counting where different element appear, and jump to the next same element.
The answers should be like this:
?- count(a,[a,a,a,a,b,a,a,a],X).
X = [4,3]
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],X).
X = [3,1,2,4]
The code I wrote for count/3 is:
count(_, [], []).
count(X, [X | T], N) :-
count(X, T, N1),
!,
N is N1 + 1.
count(X, [_ | T], N) :-
count(X, T, N).
I don't know how to make it return a list of number.
Can anyone help me?
Thanks.
Here's how you can do it and preserve logical-purity!
In the following, we use the meta-predicates (splitlistIfAdj/3,
tfilter/3, and
maplist/3) and reified term equality/inequality predicates ((=)/3 and dif/3).
Let's take E = a and Xs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a] and build up count/3 step by step:
First, let Xs1 contain the runs of items in Xs0:
?- Xs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a], splitlistIfAdj(dif,Xs0,Xs1).
Xs0 = [ a,a,a, b, a, b, a,a, b, a,a,a,a ],
Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]].
The list of runs Xs1 contains all runs. Let Xs2 contain only the ones we are interested in:
?- Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]], tfilter(\[X|_]^(X=a),Xs1,Xs2).
Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]],
Xs2 = [[a,a,a], [a], [a,a], [a,a,a,a]].
Almost done! At last, we map Xs2 (a list of E-runs) to the respective run lengths Xs:
?- Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]], maplist(length,Xs2,Xs).
Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]],
Xs = [ 3, 1, 2, 4].
Now, let's put it all together!
count(E,Xs0,Xs) :-
splitlistIfAdj(dif,Xs0,Xs1),
tfilter(E+\[X|_]^(X=E),Xs1,Xs2), % works for _any_ item E
maplist(length,Xs2,Xs).
Let's run some queries:
?- count(a,[a,a,a,a,b,a,a,a],Xs).
Xs = [4,3]. % succeeds deterministically
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
Xs = [3,1,2,4]. % succeeds deterministically
As the code is monotone, we get logically sound answers for more general queries, too:
?- count(E,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
Xs = [3,1,2,4], E = a ;
Xs = [1,1,1], E = b ;
Xs = [], dif(E,a), dif(E,b) .
The idea in my answer is to keep the list of run lengths open, and add a new element to it when a run is over:
count(_, [], []).
count(Item, [Head|Tail], Counts) :-
count(Item, [Head|Tail], 0, Counts).
count(_, [], CurrentCount, [CurrentCount]).
count(Item, [Item|Tail], CurrentCount, Counts) :-
CurrentCountP1 is CurrentCount + 1,
count(Item, Tail, CurrentCountP1, Counts).
count(Item, [Head|Tail], CurrentCount, [CurrentCount|Counts]) :-
dif(Head, Item),
count(Item, Tail, 0, Counts).
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a], X).
X = [3, 1, 2, 4] ;
false.
Related
I need to find the combinations in a list of lists. For example, give the following list,
List = [[1, 2], [1, 2, 3]]
These should be the output,
Comb = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]
Another example:
List = [[1,2],[1,2],[1,2,3]]
Comb = [[1,1,1],[1,1,2],[1,1,3],[1,2,1],[1,2,2],[1,2,3]....etc]
I know how to do it for a list with two sublists but it needs to work for any number of sublists.
I'm new to Prolog, please help.
This answer hunts the bounty offered "for a pure solution that also takes into account for Ess".
Here we generalize this previous
answer like so:
list_crossproduct(Xs, []) :-
member([], Xs).
list_crossproduct(Xs, Ess) :-
Ess = [E0|_],
same_length(E0, Xs),
maplist(maybelonger_than(Ess), Xs),
list_comb(Xs, Ess).
maybelonger_than(Xs, Ys) :-
maybeshorter_than(Ys, Xs).
maybeshorter_than([], _).
maybeshorter_than([_|Xs], [_|Ys]) :-
maybeshorter_than(Xs, Ys).
list_crossproduct/2 gets bidirectional by relating Xs and Ess early.
?- list_comb(Xs, [[1,2,3],[1,2,4],[1,2,5]]).
nontermination % BAD!
?- list_crossproduct(Xs, [[1,2,3],[1,2,4],[1,2,5]]).
Xs = [[1],[2],[3,4,5]] % this now works, too
; false.
Sample query having multiple answers:
?- list_crossproduct(Xs, [[1,2,3],[1,2,4],[1,2,5],X,Y,Z]).
X = [1,2,_A],
Y = [1,2,_B],
Z = [1,2,_C], Xs = [[1],[2],[3,4,5,_A,_B,_C]]
; X = [1,_A,3],
Y = [1,_A,4],
Z = [1,_A,5], Xs = [[1],[2,_A],[3,4,5]]
; X = [_A,2,3],
Y = [_A,2,4],
Z = [_A,2,5], Xs = [[1,_A],[2],[3,4,5]]
; false.
For completeness, here is the augmented version of my comment-version. Note nilmemberd_t/2 which is inspired by memberd_t/2.
nilmemberd_t([], false).
nilmemberd_t([X|Xs], T) :-
if_(nil_t(X), T = true, nilmemberd_t(Xs, T)).
nil_t([], true).
nil_t([_|_], false).
list_comb(List, []) :-
nilmemberd_t(List, true).
list_comb(List, Ess) :-
bagof(Es, maplist(member,Es,List), Ess).
Above version shows that "only" the first clause was missing in my comment response. Maybe even shorter with:
nilmemberd([[]|_]).
nilmemberd([[_|_]|Nils]) :-
nilmemberd(Nils).
This should work for Prologs without constraints. With constraints, bagof/3 would have to be reconsidered since copying constraints is an ill-defined terrain.
Here's a way to do it using maplist/3 and append/2:
list_comb([], [[]]).
list_comb([Xs|Xss], Ess) :-
Xs = [_|_],
list_comb(Xss, Ess0),
maplist(aux_x_comb(Ess0), Xs, Esss1),
append(Esss1, Ess).
aux_x_comb(Ess0, X, Ess1) :-
maplist(head_tail_list(X), Ess0, Ess1).
head_tail_list(X, Xs, [X|Xs]).
Sample query:
?- list_comb([[a,b],[f,g],[x,y,z]], Ess).
Ess = [[a,f,x],[a,f,y],[a,f,z],
[a,g,x],[a,g,y],[a,g,z],
[b,f,x],[b,f,y],[b,f,z],
[b,g,x],[b,g,y],[b,g,z]].
Here's how it works!
As an example, consider these goals:
list_comb([[a,b],[f,g],[x,y,z]], Ess)
list_comb([ [f,g],[x,y,z]], Ess0)
How can we get from Ess0 to Ess?
We look at the answers to the
latter query:
?- list_comb([[f,g],[x,y,z]], Ess0).
Ess0 = [[f,x],[f,y],[f,z], [g,x],[g,y],[g,z]].
... place a before [f,x], ..., [g,z] ...
?- maplist(head_tail_list(a),
[[f,x],[f,y],[f,z],
[g,x],[g,y],[g,z]], X).
X = [[a,f,x],[a,f,y],[a,f,z],
[a,g,x],[a,g,y],[a,g,z]].
... then do the same for b.
maplist(aux_x_comb) helps us handle all items:
?- maplist(aux_x_comb([[f,x],[f,y],[f,z],
[g,x],[g,y],[g,z]]),
[a,b], X).
X = [[[a,f,x],[a,f,y],[a,f,z],
[a,g,x],[a,g,y],[a,g,z]],
[[b,f,x],[b,f,y],[b,f,z],
[b,g,x],[b,g,y],[b,g,z]]].
To get from a list of lists to a list use append/2.
I hope this explanation was more eludicating than confusing:)
A twist in #false's approach:
%list_comb( ++LL, -Ess)
list_comb( LL, Ess):-
is_list( LL),
maplist( is_list, LL),
findall( Es, maplist( member, Es, LL), Ess).
Testing:
41 ?- list_comb( [[1,2],[1],[1]], X).
X = [[1, 1, 1], [2, 1, 1]].
42 ?- list_comb( [[1,2],[1],[1,2,3]], X).
X = [[1, 1, 1], [1, 1, 2], [1, 1, 3], [2, 1, 1], [2, 1, 2], [2, 1, 3]].
43 ?- list_comb( [[1,2],[],[1,2,3]], X).
X = [].
44 ?- list_comb( [[1,2],t,[1,2,3]], X).
false.
45 ?- list_comb( t, X).
false.
I'm trying to make a code that generates all subsets of a set in order.
That is, calling subset([1,2,3], X) should generate
X = [];
X = [1];
X = [2];
X = [3];
X = [1,2];
X = [1,3];
X = [2,3];
X = [1,2,3].
The internal order isn't all that important, only that the smallest subsets are listed first (i.e I don't care if [2,3] comes before [1,2], only that 1, [2] and [3] are before [2,3]).
--
I've tried two approaches thus far. First I tried making the predicate myself...
subset([], []).
subset(List, []).
subset(List, [N]) :-
member(N, List).
subset(List, [N|Rest]) :-
!,
nth0(I, List, N),
findall(E, (nth0(J, List, E), J > I), NewList),
subset2(NewList, Rest).
...but it doesn't even come close to working as intended. Secondly I tried making the powerset (using this subset predicate) and ordering with list_to_ord_set/2, but I couldn't get it to work either.
Help?
Always also consider using DCG notation when describing lists.
For example:
list_sublist(Ls0, Ls) :-
same_length(Ls0, Ls1),
append(Ls, _, Ls1),
phrase(sublist(Ls0), Ls).
sublist([]) --> [].
sublist([L|Ls]) --> ( [] ; [L] ), sublist(Ls).
Sample query:
?- list_sublist([a,b,c], Ls).
Ls = [] ;
Ls = [c] ;
Ls = [b] ;
Ls = [a] ;
Ls = [b, c] ;
Ls = [a, c] ;
Ls = [a, b] ;
Ls = [a, b, c] ;
false.
Another example:
?- list_sublist(Ls, [b,c]).
Ls = [b, c] ;
Ls = [_G511, b, c] ;
Ls = [b, _G514, c] ;
Ls = [b, c, _G517] ;
etc.
Most general case:
?- list_sublist(Xs, Ys).
Xs = Ys, Ys = [] ;
Xs = [_G513],
Ys = [] ;
Xs = Ys, Ys = [_G513]
Xs = [_G513, _G516],
Ys = [] ;
etc.
I've found a not so elegant solution... it requires a cut and some builtins
subset(Xs, Ys) :-
length(Xs, L),
between(0, L, N),
length(Ys, N),
assign(Xs, Ys).
assign(_, []) :- !.
assign([X|Xs], [X|Ys]) :-
assign(Xs, Ys).
assign([_|Xs], Ys) :-
assign(Xs, Ys).
as noted by #Fatalize, we can avoid the cut, just forcing the empty list on first argument of 1^ clause:
assign([], []).
assign([X|Xs], [X|Ys]) :-
assign(Xs, Ys).
assign([_|Xs], Ys) :-
assign(Xs, Ys).
I avoided to swap 2^ and 3^ clauses, so the 'natural' order is still nicely preserved
I need to write a Prolog predicate take(L, N, L1) which succeeds if list L1 contains the first N elements of list L, in the same order. For example:
?- take([5,1,2,7], 3, L1).
L1 = [5,1,2]
?- take([5,1,2,7], 10, L1).
L1 = [5,1,2,7]
Prolog thus far is making little sense to me, and I'm having a hard time breaking it down. Here is what I have so far:
take([H|T], 0, []).
take([H|T], N, L1) :-
take(T, X, L2),
X is N-1.
Can you please explain what I did wrong here?
Here is a definition that implements the relational counterpart to take in functional languages like Haskell1. First, the argument order should be different which facilitates partial application. There is a cut, but only after the error checking built-in (=<)/2 which produces an instantiation_error should the argument contain a variable.
take(N, _, Xs) :- N =< 0, !, N =:= 0, Xs = [].
take(_, [], []).
take(N, [X|Xs], [X|Ys]) :- M is N-1, take(M, Xs, Ys).
?- take(2, Xs, Ys).
Xs = [], Ys = []
; Xs = [_A], Ys = [_A]
; Xs = [_A,_B|_C], Ys = [_A,_B].
Note how above query reads:
How can one take 2 elements from Xs to get Ys?
And there are 3 different answers. If Xs is empty, then so is Ys. If Xs is a list with one element, then so is Ys. If Xs has at least 2 elements, then those two are Ys.
1) The only difference being that take(-1, Xs,Ys) fails (for all Xs, Ys). Probably the best would be to issue a domain_error similar to arg(-1,s(1),2)
findall/3 it's a bit the 'swiss knife' of Prolog. I would use this snippet:
take(Src,N,L) :- findall(E, (nth1(I,Src,E), I =< N), L).
The code by #CapelliC works if the instantiation is right; if not, it can show erratic behavior:
?- take(Es, 0, Xs).
**LOOPS** % trouble: goal does not terminate
?- take([A,_], 1, [x]).
true. % trouble: variable A remains unbound
To safeguard against this you can use
iwhen/2 like so:
take(Src, N, L) :-
iwhen(ground(N+Src), findall(E, (nth1(I,Src,E), I =< N), L)).
Sample queries run with SWI-Prolog 8.0.0:
?- take([a,b,c,d,e,f], 3, Ls).
Ls = [a,b,c].
?- take([a,b,c,d,e,f], N, Ls).
ERROR: Arguments are not sufficiently instantiated
?- take(Es, 0, Xs).
ERROR: Arguments are not sufficiently instantiated
?- take([A,_], 1, [x]).
ERROR: Arguments are not sufficiently instantiated
Safer now!
The obvious solution would be:
take(List, N, Prefix) :-
length(List, Len),
( Len =< N
-> Prefix = List
; length(Prefix, N),
append(Prefix, _, List)
).
Less thinking means less opportunity for mistakes. It also makes the predicate more general.
your base case is fine
take([H|T], 0, []).
And also you can say what if N is 1
take([H|T],1,[H]).
But you recursive case some variable is not defined like L2. So we can write this as
take([X|T1],N,[X|T2]):-
N>=0,
N1 is N-1,
take(T1,N1,T2).
which case all varibles are pattern-matched.
take(L, N, L1) :- length(L1, N), append(L1, _, L).
This is performant, general and deterministic:
first_elements_of_list(IntElems, LongLst, ShortLst) :-
LongLst = [H|T],
( nonvar(IntElems) -> Once = true
; is_list(ShortLst) -> Once = true
; Once = false
),
first_elements_of_list_(T, H, 1, IntElems, ShortLst),
(Once = true -> ! ; true).
first_elements_of_list_([], H, I, I, [H]).
first_elements_of_list_([_|_], H, I, I, [H]).
first_elements_of_list_([H|LongLst], PrevH, Upto, IntElems, [PrevH|ShortLst]) :-
Upto1 is Upto + 1,
first_elements_of_list_(LongLst, H, Upto1, IntElems, ShortLst).
Result in swi-prolog:
?- first_elements_of_list(N, [a, b, c], S).
N = 1,
S = [a] ;
N = 2,
S = [a,b] ;
N = 3,
S = [a,b,c].
?- first_elements_of_list(2, [a, b, c], S).
S = [a,b].
Below is a variant which also supports:
?- first_elements_of_list_more(10, [5, 1, 2, 7], L1).
L1 = [5,1,2,7].
first_elements_of_list_more(IntElems, [H|LongLst], [H|ShortLst]) :-
once_if_nonvar(IntElems, first_elements_of_list_more_(LongLst, 1, IntElems, ShortLst)).
first_elements_of_list_more_([], Inc, Elems, []) :-
(var(Elems) -> Inc = Elems
; Elems >= Inc).
first_elements_of_list_more_([_|_], E, E, []).
first_elements_of_list_more_([H|LongLst], Upto, IntElems, [H|ShortLst]) :-
succ(Upto, Upto1),
first_elements_of_list_more_(LongLst, Upto1, IntElems, ShortLst).
once_if_nonvar(Var, Expr) :-
nonvar(Var, Bool),
call(Expr),
(Bool == true -> ! ; true).
nonvar(Var, Bool) :-
(nonvar(Var) -> Bool = true ; Bool = false).
This is what I've got where this deletes the last element of the list only.
delete([_], []).
delete([X|Xs], [X|Last]) :- delete(Xs, Last).
The loop should run until the original list is empty an it returns the new list.
It's somewhat similar to subsets.
You can improve upon you definition, avoiding unwanted choice points, by rewriting it as:
delete([Head| Tail], List) :-
delete(Tail, Head, List).
delete([], _, []).
delete([Next| Tail], Previous, [Previous| List]) :-
delete(Tail, Next, List).
Some sample calls:
?- delete([1,2,3], L).
L = [1, 2].
?- delete([], L).
false.
?- delete([1], L).
L = [].
?- delete(L, [1,2,3]).
L = [1, 2, 3, _].
?- delete(L1, L2).
L1 = [_A],
L2 = [] ? ;
L1 = [_A,_B],
L2 = [_A] ? ;
L1 = [_A,_B,_C],
L2 = [_A,_B] ? ;
L1 = [_A,_B,_C,_D],
L2 = [_A,_B,_C] ?
...
may be :
delete_last(In, Out) :-
append(Out, [_], In).
i'm starting up learning prolog (i use SWI-prolog) and i did a simple exercise in which i have 2 lists and i want to calculate their intersection and union.
Here is my code that works pretty well but i was asking myself if there is a better way to do it as i don't like to use the CUT operator.
intersectionTR(_, [], []).
intersectionTR([], _, []).
intersectionTR([H1|T1], L2, [H1|L]):-
member(H1, L2),
intersectionTR(T1, L2, L), !.
intersectionTR([_|T1], L2, L):-
intersectionTR(T1, L2, L).
intersection(L1, L2):-
intersectionTR(L1, L2, L),
write(L).
unionTR([], [], []).
unionTR([], [H2|T2], [H2|L]):-
intersectionTR(T2, L, Res),
Res = [],
unionTR([], T2, L),
!.
unionTR([], [_|T2], L):-
unionTR([], T2, L),
!.
unionTR([H1|T1], L2, L):-
intersectionTR([H1], L, Res),
Res \= [],
unionTR(T1, L2, L).
unionTR([H1|T1], L2, [H1|L]):-
unionTR(T1, L2, L).
union(L1, L2):-
unionTR(L1, L2, L),
write(L).
Keep in mind that i want to have just 1 result, not multiple results (even if correct) so running the code with this:
?- intersect([1,3,5,2,4] ,[6,1,2]).
should exit with:
[1,2]
true.
and not with
[1,2]
true ;
[1,2]
true ;
etc...
The same must be valid for union predicate.
As i said my code works pretty well but please suggest better ways to do it.
Thanks
Also, not sure why you're dead against cuts, so long as their removal would not change the declaritive meaning of the code, as per your link. For example:
inter([], _, []).
inter([H1|T1], L2, [H1|Res]) :-
member(H1, L2),
inter(T1, L2, Res).
inter([_|T1], L2, Res) :-
inter(T1, L2, Res).
test(X):-
inter([1,3,5,2,4], [6,1,2], X), !.
test(X).
X = [1, 2].
In the test bit where I call the code, I'm just saying do the intersection but I'm only interested in the first answer. There are no cuts in the predicate definitions themselves.
The following is based on my previous answer to Remove duplicates in list (Prolog);
the basic idea is, in turn, based on #false's answer to Prolog union for A U B U C.
What message do I want to convey to you?
You can describe what you want in Prolog with logical purity.
Using if_/3 and (=)/3 a logically pure implementation can be
both efficient (leaving behind choice points only when needed)
and monotone (logically sound with regard to generalization / specialization).
The implementation of #false's predicates if_/3 and (=)/3 does use meta-logical Prolog features internally, but (from the outside) behaves logically pure.
The following implementation of list_list_intersection/3 and list_list_union/3 uses list_item_isMember/3 and list_item_subtracted/3, defined in a previous answer:
list_list_union([],Bs,Bs).
list_list_union([A|As],Bs1,[A|Cs]) :-
list_item_subtracted(Bs1,A,Bs),
list_list_union(As,Bs,Cs).
list_list_intersection([],_,[]).
list_list_intersection([A|As],Bs,Cs1) :-
if_(list_item_isMember(Bs,A), Cs1 = [A|Cs], Cs1 = Cs),
list_list_intersection(As,Bs,Cs).
Here's the query you posted as part of your question:
?- list_list_intersection([1,3,5,2,4],[6,1,2],Intersection).
Intersection = [1, 2]. % succeeds deterministically
Let's try something else... The following two queries should be logically equivalent:
?- A=1,B=3, list_list_intersection([1,3,5,2,4],[A,B],Intersection).
A = 1,
B = 3,
Intersection = [1, 3].
?- list_list_intersection([1,3,5,2,4],[A,B],Intersection),A=1,B=3.
A = 1,
B = 3,
Intersection = [1, 3] ;
false.
And... the bottom line is?
With pure code it's easy to stay on the side of logical soundness.
Impure code, on the other hand, more often than not acts like "it does what it should" at first sight, but shows all kinds of illogical behaviour with queries like the ones shown above.
Edit 2015-04-23
Neither list_list_union(As,Bs,Cs) nor list_list_intersection(As,Bs,Cs) guarantee that Cs doesn't contain duplicates. If that bothers you, the code needs to be adapted.
Here are some more queries (and answers) with As and/or Bs containing duplicates:
?- list_list_intersection([1,3,5,7,1,3,5,7],[1,2,3,1,2,3],Cs).
Cs = [1, 3, 1, 3].
?- list_list_intersection([1,2,3],[1,1,1,1],Cs).
Cs = [1].
?- list_list_union([1,3,5,1,3,5],[1,2,3,1,2,3],Cs).
Cs = [1, 3, 5, 1, 3, 5, 2, 2].
?- list_list_union([1,2,3],[1,1,1,1],Cs).
Cs = [1, 2, 3].
?- list_list_union([1,1,1,1],[1,2,3],Cs).
Cs = [1, 1, 1, 1, 2, 3].
Edit 2015-04-24
For the sake of completeness, here's how we could enforce that the intersection and the union are sets---that is lists that do not contain any duplicate elements.
The following code is pretty straight-forward:
list_list_intersectionSet([],_,[]).
list_list_intersectionSet([A|As1],Bs,Cs1) :-
if_(list_item_isMember(Bs,A), Cs1 = [A|Cs], Cs1 = Cs),
list_item_subtracted(As1,A,As),
list_list_intersectionSet(As,Bs,Cs).
list_list_unionSet([],Bs1,Bs) :-
list_setB(Bs1,Bs).
list_list_unionSet([A|As1],Bs1,[A|Cs]) :-
list_item_subtracted(As1,A,As),
list_item_subtracted(Bs1,A,Bs),
list_list_unionSet(As,Bs,Cs).
Note that list_list_unionSet/3 is based on list_setB/2, defined here.
Now let's see both list_list_intersectionSet/3 and list_list_unionSet/3 in action:
?- list_list_unionSet([1,2,3,1,2,3,3,2,1],[4,5,6,2,7,7,7],Xs).
Xs = [1, 2, 3, 4, 5, 6, 7].
?- list_list_intersectionSet([1,2,3,1,2,3,3,2,1],[4,5,6,2,7,7,7],Xs).
Xs = [2].
Edit 2019-01-30
Here is an additional query taken from #GuyCoder's comment (plus two variants of it):
?- list_list_unionSet(Xs,[],[a,b]).
Xs = [a,b]
; Xs = [a,b,b]
; Xs = [a,b,b,b]
...
?- list_list_unionSet([],Xs,[a,b]).
Xs = [a,b]
; Xs = [a,b,b]
; Xs = [a,b,b,b]
...
?- list_list_unionSet(Xs,Ys,[a,b]).
Xs = [], Ys = [a,b]
; Xs = [], Ys = [a,b,b]
; Xs = [], Ys = [a,b,b,b]
...
With the old version of list_item_subtracted/3, above queries didn't terminate existentially.
With the new one they do.
As the solution set size is infinite, none of these queries terminate universally.
To cheat slightly less than my first answer, you could use the findall higher order predicate which gets Prolog to do the recursion for you :
4 ?- L1=[1,3,5,2,4], L2=[6,1,2], findall(X, (nth0(N, L1, X), member(X, L2)), Res).
L1 = [1, 3, 5, 2, 4],
L2 = [6, 1, 2],
Res = [1, 2].
If the aim is to just 'get the job done', then swi prolog has built in primitives for exactly this purpose:
[trace] 3 ?- intersection([1,3,5,2,4] ,[6,1,2], X).
intersection([1,3,5,2,4] ,[6,1,2], X).
X = [1, 2].
[trace] 4 ?- union([1,3,5,2,4] ,[6,1,2], X).
X = [3, 5, 4, 6, 1, 2].
Try this, analogue to union/3 here:
:- use_module(library(clpfd)).
member(_, [], 0).
member(X, [Y|Z], B) :-
(X #= Y) #\/ C #<==> B,
member(X, Z, C).
intersect([], _, []).
intersect([X|Y], Z, T) :-
freeze(B, (B==1 -> T=[X|R]; T=R)),
member(X, Z, B),
intersect(Y, Z, R).
It works if the elements are integer, and doesn't leave any choise point:
?- intersect([X,Y],[Y,Z],L).
freeze(_15070, (_15070==1->L=[X, Y];L=[Y])),
_15070 in 0..1,
_15166#\/_15168#<==>_15070,
_15166 in 0..1,
X#=Y#<==>_15166,
X#=Z#<==>_15168,
Y#=Z#<==>_15258,
_15168 in 0..1,
_15258 in 0..1.
?- intersect([X,Y],[Y,Z],L), X=1, Y=2, Z=3.
X = 1,
Y = 2,
Z = 3,
L = [2].
?- intersect([X,Y],[Y,Z],L), X=3, Y=2, Z=3.
X = Z, Z = 3,
Y = 2,
L = [3, 2].
And finally (really), you could use findall to find all the solutions, then use nth0 to extract the first one, which will give you the result you want without cuts, and keeps the predicates nice and clean, without have any additional predicates to trap/stop prolog doing what it does best - backtracking and finding multiple answers.
Edit: It's arguable that putting in extra predicates in the 'core logic' to prevent multiple results being generated, is as ugly/confusing as using the cuts that you are trying to avoid. But perhaps this is an academic exercise to prove that it can be done without using higher order predicates like findall, or the built-ins intersection/union.
inter([], _, []).
inter([H1|T1], L2, [H1|Res]) :-
member(H1, L2),
inter(T1, L2, Res).
inter([_|T1], L2, Res) :-
inter(T1, L2, Res).
test(First):-
findall(Ans, inter([1,3,5,2,4], [6,1,2], Ans), Ansl),
nth0(0, Ansl, First).
% Element X is in list?
pert(X, [ X | _ ]).
pert(X, [ _ | L ]):- pert(X, L).
% Union of two list
union([ ], L, L).
union([ X | L1 ], L2, [ X | L3 ]):- \+pert(X, L2), union(L1, L2, L3).
union([ _ | L1 ], L2, L3):- union(L1, L2, L3).
% Intersection of two list
inter([ ], _, [ ]).
inter([ X | L1 ], L2, [ X | L3 ]):- pert(X, L2), inter(L1, L2, L3).
inter([ _ | L1 ], L2, L3):- inter(L1, L2, L3).
I know this post is very old but I found a solution with minimum coding.
% intersection
intersection([],L1,L2,L3).
intersection([H|T],L2,L3,[H|L4]):-member(H,L2),intersection(T,L3,L3,L4).
% member
member(H,[H|T]).
member(X,[H|T]):-member(X,T).
To test the above code you should not enter L3. Here is an examples.
?- intersection([w,4,g,0,v,45,6],[x,45,d,w,30,0],L).
L = [w, 0, 45].