aman
aman

Reputation: 87

Prolog Zip Function

Im in rew to Prolog. I'm trying to write a zip function. The question goes like this.

zip(L1, L2, X): The list X is formed by “zipping” the first 2 arguments.

the result should be like this:

?- zip([a, b, c], [x, y, z], X).
L = [a, x, b, y, c, z]
?- zip([a, b], [x, y, z], X).
false
?- zip([a, b, c, d], X, [a, p, b, q, c, r, d, s]).
X = [p, q, r, s]

I have done this so far. I can get the result for 1st 3rd but not the 2nd one. Can anybody can help me solving it for the 2nd one? thank you

zip([X],[Y],[X,Y]).  
zip([], [], []).
zip([X|Xs], [Y|Ys], [X,Y|Zs]) :-
   zip(Xs,Ys,Zs).

zip([X|Xs],[],[X|Xs]).
zip([Y|Ys],[],[Y|Ys]).

zip(Xs, [], Xs).
zip([], Ys, Ys).

How do I define this function where: allsame(L): The list L contains identical elements. I should get this.

?- allsame([b, b, b]).
true
?- allsame([c, c, c, Y, c, c, X, c]).
X = c, Y = c

Upvotes: 3

Views: 6317

Answers (2)

lurker
lurker

Reputation: 58244

@m09 gave the correct answer. But I'd like to explain why what you have isn't correct:

(1) zip([X],[Y],[X,Y]).

This rule says that [X,Y] is what you get when you zip [X] with [Y]. That is correct, and will not lead to a problem. The rule is simply redundant with the rules below (which I'll explain...).

(2) zip([], [], []).

This rule says [] is what you get when you zip [] with [] which is correct and as simple a rule as you can have for zip.

(3) zip([X|Xs], [Y|Ys], [X,Y|Zs]) :-
        zip(Xs,Ys,Zs).

This rule says that [X,Y|Zs] is what you get when you zip [X|Xs] with [Y|Ys] if Zs is what you get when you zip Xs with Ys. That is also logical and correct. Notice that zip([X], [Y], [X,Y]) is zip([X|[]], [Y|[]], [X,Y|[]]). so it can be derived from rules (2) and (3). It would match rule (3) first, zip([X|[]], [Y|[]], [X,Y|Zs]) :- zip([], [], Zs)., then Zs would become [] by rule (2)`.

(4) zip([X|Xs],[],[X|Xs]).
(5) zip([Y|Ys],[],[Y|Ys]).

Rule (4) says [X|Xs] is what you get when you zip [X|Xs] with []. Rule (5) says exactly the same thing, logically, only with a different variable name. These are incorrect, since that would mean, for example, zip([a,b,c], [], Z) would be true if Z = [a,b,c].

(6) zip(Xs, [], Xs).

This rule says that Xs is what you get when you zip Xs with []. Or stated another way, any input, zipped with [], would be that input value again. It wouldn't even have to be a list! This is clearly incorrect. Queries like zip(x, [], Z) would succeed with Z = x, and zip(friend(bill,mary), [], Z) would succeed with Z = friend(bill,mary).

(7) zip([], Ys, Ys).

This rule says that Ys is what you get when you zip [] with Ys. It is incorrect for the same reason (6) is incorrect. In fact, this rule, combined with (2) and (3) are why the query zip([a, b], [x, y, z], X). will yield a result rather than fail. Rules (2) and (3) will recurse to zip([b], [y,z], [b,y|T]) :- zip([], [z], T). and then zip([], [z], T) will finally succeed on rule (7) with T = [z], and ultimately yielding a final result to zip([a, b], [x, y, z], X) of X = [a, x, b, y, z].

Upvotes: 4

m09
m09

Reputation: 7493

You had it:

zip([], [], []).
zip([X|Xs], [Y|Ys], [X,Y|Zs]) :- zip(Xs,Ys,Zs).

This alone is enough to define the relation you're seeking. The extra clauses don't help.

Test:

?- zip([a, b, c], [x, y, z], X).
X = [a, x, b, y, c, z].

?- zip([a, b], [x, y, z], X).
false.

?- zip([a, b, c, d], X, [a, p, b, q, c, r, d, s]).
X = [p, q, r, s].

Upvotes: 7

Related Questions