合并Prolog中两个列表中的备用元素

时间:2012-05-20 23:46:09

标签: list prolog

如果列表Z是列表X和Y中的备用元素的合并,我需要编写一个成功的Prolog谓词mergealt(X,Y,Z)

输入和输出如下:

?- mergealt([1,2,3,4],[6,7,8],Z).
Z = [1, 7, 3] .
?- mergealt([1,2,3,4],[6,7,8,9],Z).
Z = [1, 7, 3, 9] .
?- mergealt([1,2,3,4],[6,7,8,9,10],Z).
Z = [1, 7, 3, 9] .

我真的不明白递归。我怎样才能开始解决这个问题?

2 个答案:

答案 0 :(得分:5)

Prolog可以被认为是声明性语言的“旗手”。 因此,请尝试自上而下地描述您的问题:

mergealt(X, Y, Z) :-
  'take first element from X and put it in Z',
  'discard first element from Y',
  'mergealt rest-of-X and rest-of-Y, but exchange them'.

如果X中没有元素,则无法完成第一步。 这一事实凸显了递归终止案例。最初,Prolog没有使用if then else,而是替代方案被陈述为不同的规则:

mergealt([], _Y, []).

在这里你可以看到pattern matching在第一个参数上它是区分备选方案的关键,而在上下文中,Z将绑定添加到空列表中。 Y未使用,因此将其标记为 anonymus 占位符,以避免出现警告。

然后这个更简单的案例表明我们应该使用模式匹配来完成那些冗长的描述。看看您是否可以使用这些指南完成此过程:

mergealt([X|Xs], Y, [X|Zs]) :-
  % take first element from X and put it in Z : done in the head
  % discard first element from Y : see below
  % mergealt rest-of-X and rest-of-Y, but exchange them'. : make your recursive call

discard_first_element([_|Rest], Rest).
% why is this necessary? do you see where it fails if we don't specify this case?
discard_first_element([], []).

答案 1 :(得分:2)

  • 请注意,结果始终以第一个列表的第一个元素开头。
  • 这意味着,如果第一个列表为空,则立即知道答案。
  • 另请注意,如果它不为空,我们已经知道结果的第一项,因此我们需要使用mergealt来计算其余项。但是“其余的”将第二个列表的第二个项目作为结果的第一个项目,正如我们上面所说的,这意味着调用mergealt来计算它必须具有第一项作为第一项清单(是的,这是棘手的部分)。