1

Hey I'm trying to append two list with no "double" members

for example

A = [a, b, c]
B = [x, c, q]

then ->

append2(A,B,P)

P= [a,b,c,x,q]

I write this code, but it doesn't work...

not_member(_, []).
not_member(X, [Y|Ys]) :- X \= Y, not_member(X, Ys).

append2(A, [], A).
append2([], A, A).
append2([h1|ls], B, [h1|P]) :- not_member(h1, B), !, append2(ls, B, P).
append2([h1|ls], B, P) :-  member(h1, P), append2(ls, B, P).

Thanks for helping :)

false
  • 10,264
  • 13
  • 101
  • 209
Aviram Fireberger
  • 3,910
  • 5
  • 50
  • 69
  • 1
    One major problem is that you are using atoms instead of variables. `h1` is an atom (not variable). `H1` would be a variable (begins with a capital letter). Same for your `ls`. You need `LS` or `Ls`. Fix that and see how far you get. Also it's not clear why you had to define `not_member`. In your `append2` you could just use `\+ member(...)`. At the very least, you could define `not_member(X, L) :- \+ member(X, L).`. – lurker Jul 04 '13 at 14:16
  • Hey , I did the changes , no for: append2([a,b,c] , [c] , P). I got: P = [a, b, c] . But for bigger input like: append2([a,b,c] , [b,x,a,u] , P). I got: ERROR: Out of global stack – Aviram Fireberger Jul 04 '13 at 14:29
  • That means you have circular logic in your code somewhere. Looks like @gusbro handed you an rewrite. – lurker Jul 04 '13 at 14:30

2 Answers2

1

Assuming there are no variables in your input lists, but allowing duplicates in each list you may write:

append2(A,B,C):-
  findall(Item, append2_item(A,B,Item), C).

append2_item(A,_,ItemA):-
  append(HeadA, [ItemA|_], A),
  \+ member(ItemA, HeadA).
append2_item(A,B,ItemB):-
  append(HeadB, [ItemB|_], B),
  \+ member(ItemB, HeadB),
  \+ member(ItemB, A).

First clause of append2_item/3 selects (ordered) distinct items from the first list. Second clause of append2_item/3 selects (ordered) distinct items from the second list which are not present in the first list. append2/3 just collects those elements.

Test case:

?- append2([a,b,c,a],[x,c,q,x],C).
C = [a, b, c, x, q].
gusbro
  • 22,357
  • 35
  • 46
  • 1
    @Kika: [findall/3](http://www.swi-prolog.org/pldoc/man?predicate=findall/3) collects the first argument (template) from executing the goal from the second argument (with backtracking to test all solutions) and unifies the third argument with the list of collected templates. – gusbro Jul 04 '13 at 14:45
1

Check out the pure code in my answer to the related question "intersection and union of 2 lists"!

Telling from your requirements, predicate list_list_union/3 is just what you are looking for:

?- list_list_union([a,b,c],[x,c,q],Ls).
Ls = [a,b,c,x,q].                               % succeeds deterministically

list_list_union/3 is monotone, so we get sound answers even when using non-ground terms:

?- As = [_,_,_], Bs = [_,_,_], list_list_union(As,Bs,Ls), As = [a,b,c], Bs = [x,c,q].
As = [a,b,c], Bs = [x,c,q], Ls = [a,b,c,x,q] ;  % logically sound result
false.
Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166