Reputation: 93
I need to merge two lists in Prolog. On input should be predicate merge/3
.
Should work like this:
?- merge([6,4,b,8], [5,b,s,6], X).
X = [6, 4, b, 8, 5, s].
What I have tried:
%rules
merge(A, B, X):-
merge(A, B, B, X).
merge([], X, _, X).
merge([Head|L1], [Head|L2], Tmp, [Head|X]) :-
merge(L1, L2, Tmp, X),
!.
merge(L1, [_|L2], Tmp, X) :-
merge(L1, L2, Tmp, X),
!.
merge([A|L1], [], Tmp, [A|X]) :-
merge(L1, Tmp, Tmp, X),
!.
What I get:
?- merge([1,2,a,3], [5,d,a,1], X).
X = [1, 2, a, 3, 5, d, a, 1].
What I expect:
?- merge([1,2,a,3], [5,d,a,1], X).
X = [1, 2, a, 3, 5, d].
Upvotes: 0
Views: 3990
Reputation: 5645
This can be done by rewriting built-in predicates ! e.g :
my_append([], R, R) .
my_append([H|T], R1, [H|R2]) :-
my_append(T, R1, R2).
my_member(H, [H|_]).
my_member(H, [_|T]) :-
my_member(H, T).
So, I can say that merging L with an empty list gives this list L
merge(L, [], L).
Now, to merge two lists, I look at the first element of the second list.
If it is in the first list, I ignore it and I merge the first list, with the rest of the second.
If not, I add this first element at the end of the first list and I merge the new first list with the rest of the second.
I must say that it's not very efficient !!
merge(L, [H| T], R) :-
( my_member(H, L)
-> merge(L, T, R)
; my_append(L, [H], L1),
merge(L1, T, R)).
Upvotes: 1
Reputation:
If the order of the elements does not somehow depend on the order of the two input lists, this is an idiomatic Prolog solution:
?- append([6,4,b,8], [5,b,s,6], A), sort(A, B).
A = [6, 4, b, 8, 5, b, s, 6],
B = [4, 5, 6, 8, b, s].
If the order is important, you need to explain how exactly.
And some comments on the code you show. The names that you have chosen for your predicates: both "join" and "merge" have well-established meanings different from what you seem to be attempting to achieve ("join" as in relational databases, "merge" as in "merge two ordered lists"). What you are doing is rather a "union" (and by the way, click on this link and read the code!).
Also, it is almost always a mistake (not an error, but a mistake) to have a cut as the last subgoal of a clause body. Having multiple clauses to a predicate that are not obviously mutually exclusive (as the last 3 of the 4 clauses to your merge/4
) is commonly a design flaw (not a mistake).
Upvotes: 2