我是Prolog的新手。我已设法为下面的问题执行zip/3
谓词。任何人都可以帮助我使用pair/1
谓词吗?谢谢。
zip(L1, L2, L)
:列表L是通过“压缩”前两个参数形成的。
结果应该是这样的:
?- zip([a, b, c], [x, y, z], L).
L = [a, x, b, y, c, z]
?- zip([a, b], [x, y, z], L).
false
?- zip([a, b, c, d], X, [a, p, b, q, c, r, d, s]).
X = [p, q, r, s]
解决方案:
zip([], [], []).
zip([X|Xs], [Y|Ys], [X,Y|Zs]) :-
zip(Xs,Ys,Zs).
pair(L)
:L中的所有元素恰好出现两次。结果:
?- pair([a, b, b, c, a, c]).
true
?- pair([a, a, b, b, a, a]).
false
?- pair([a, a, b, c, d, d, c, X]).
X = b
答案 0 :(得分:2)
逻辑的第一遍会说:
[X,X]
是一个列表,其元素只显示两次[H|T]
是一个列表,如果我们从H
移除T
(产生T1
),则其元素只显示两次,并且H
不包含在T1
中,T1
是一个列表,其元素只显示两次。这会导致:
twice([H|T]) :-
select(H, T, T1), % T1 is T with one occurrence of H removed
\+ member(H, T1),
twice(T1).
twice([X,X]).
这适用于:
?- twice([a, b, b, c, a, c]).
true ;
false.
?- twice([a, a, b, b, a, a]).
false.
可是:
?- twice([a, a, b, c, d, d, c, X]).
false.
这样做的原因是,如果member(X, T)
可以找到X
和T
中的变量实例化,那么T
将成功。如果X
有一个变量而member(X, T)
是一个原子,则可以通过将T
中的变量与X
统一来使member
成为真。
所以我们需要一个"修改" is_in
谓词(我们将调用twice([H|T]) :-
select(H, T, T1), % T1 is T with one occurrence of H removed
\+ is_in(H, T1),
twice(T1).
twice([X,X]).
is_in(X, [H|_]) :- % X is in [H|_] if...
X == H. % X and H are the same ("member" would use '=' here)
is_in(X, [_|T]) :- % X is in [_|T] if...
is_in(X, T). % X is in T
),其行为符合我们的要求:
?- twice([a, b, b, c, a, c]).
true ;
false.
?- twice([a, a, b, b, a, a]).
false.
?- twice([a, a, b, c, d, d, c, X]).
X = b ;
false.
然后我们得到:
==
这里的关键是b == X
,用于检查术语是否已经等于而试图实例化任何变量。如果你有b = X
它会失败,这就是我们想要的。但是,如果我们有X
,那么它会成功,因为Prolog会将b
实例化为select/3
以使其成功。
另一个关键是X
将实例化变量以成功,这对于在上面的示例中实例化twice(L)
是必要的。
上述实现的一个限制是最常见的查询L
,其中?- twice(L).
% Hmm.... I'm waiting....
是可变的,将失败:
twice/1
这可以通过控制twice([H|T]) :-
length([H|T], _), % We don't actually use the length value, so _
select(H, T, T1), % T1 is T with one occurrence of H removed
\+ is_in(H, T1),
twice(T1).
twice([X,X]).
谓词中的列表长度来解决:
?- twice(L).
L = [_G8, _G8, _G14, _G14] ;
L = [_G8, _G11, _G8, _G11] ;
L = [_G8, _G11, _G11, _G8] ;
L = [_G8, _G8, _G14, _G14, _G20, _G20] ;
L = [_G8, _G8, _G14, _G17, _G14, _G17] ;
...
然后我们也得到:
?- twice([a,b|T]).
T = [a, b] ;
T = [b, a] ;
T = [a, b, _G306, _G306] ;
T = [a, _G303, b, _G303] ;
T = [a, _G303, _G303, b] ;
T = [b, a, _G306, _G306] ;
或者:
twice([]).
最后,根据上述定义,[]
失败。如果您想将twice([X,X]).
定义为成功,则只需将twice([]).
替换为{{1}}。