Reputation: 87
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
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
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