嘿所以这是我的代码到目前为止。我只是在prolog的初学者,但我需要它在学校
firstElement([_|_], [Elem1|List1], [Elem2|List2]):-
Elem1 =< Elem2, merge([Elem1] , List1, [Elem2|List2]);
merge([], [Elem2], List2).
merge([Head|Tail], [Elem1|List1], [Elem2|List2]):-
Elem1 =< Elem2,!, add(Elem1,[Head|Tail],[Head|Tail1]),
merge([Head|Tail1], List1, [Elem2|List2]);
add(Elem2,[Head|Tail],[Head|Tail1]),
merge([Head|Tail1], [Elem1|List1], List2).
merge([Head|Tail], [], [Elem2|List2]):-
add(Elem2,[Head|Tail],[Head|Tail1]).
merge([Head|Tail], [Elem1|List1], []):-
add(Elem1,[Head|Tail],[Head|Tail1]).
merge([Head|Tail], [], []).
add(X,[],[X]).
add(X,[Y|Tail],[Y|Tail1]):-
add(X,Tail,Tail1).
我发现每次合并时它都会忘记最后一个数字,所以它最终会回归。
答案 0 :(得分:4)
我认为你的代码已经非常混乱了。一个完整的解决方案可以没有帮助者,只有几个条款。
首先让我们讨论涉及空列表的两个基本案例:
merge(X, [], X).
merge([], X, X).
你没有这些,但我看到某种认识,你需要特别在你的第二和第三个条款中处理空列表,但我认为你感到困惑和过于复杂。这两个条款实际上涵盖了三种情景。这两个列表都是空的情况是由他们两个覆盖的免费赠品,但由于这种情况可以解决merge([], [], [])
,所以它已被覆盖。这里的一个重要想法是,如果你耗尽任何一个列表,因为它们已经排序,你在另一个列表中留下的是你的结果。想一想。
这留下了有趣的案例,我们在两个列表中都有一些项目。基本上你想要做的是选择两者中较小的一个,然后重复整个其他列表和你选择的较小值的剩余部分。这是一个条款:
merge([L|Ls], [R|Rs], [L|Merged]) :-
L @< R,
merge(Ls, [R|Rs], Merged).
以下是您应该注意的事项:
L
。merge
的递归调用使用[R|Rs]
重建整个第二个列表。应该可以通过查看这个来构建另一个子句。
作为Prolog的中级用户,我自然会对使用两个子句来做这项工作有点怀疑,因为它会创建不必要的选择点。作为初学者,你很想用切割来消除这些选择点,这对你来说很糟糕。更中间的方法是使用条件运算符将两个必要的子句包含在一个中:
merge([L|Ls], [R|Rs], [N|Ns]) :-
( L @< R ->
N = L, merge(Ls, [R|Rs], Ns)
; —- other case goes here
).
专家可能会使用if_/3
来构建它:
@<(X,Y,true) :- X @< Y.
@<(X,Y,false) :- X @>= Y.
merge([L|Ls], [R|Rs], [N|Ns]) :-
if_(@<(L,R),
(N = L, merge(Ls, [R|Rs], Ns)),
( -- other case here )).
无论如何,我希望这有助于说明情况。