Zip甚至在prolog上运行

时间:2014-04-05 06:50:28

标签: prolog

我是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

1 个答案:

答案 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)可以找到XT中的变量实例化,那么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}}。