在Prolog中,我必须弄清楚如何将两个已排序的列表组合成一个排序列表。换句话说:从2个列表中我必须比较头并将最小值添加到新列表中。我想我已经走得很远,但不知何故它只是不起作用,我无法弄清楚为什么不行。 BTW我没有任何错误。它只是给了false
。
所以,我希望有人可以告诉我我做错了什么。
sort([],L,L).
sort(L,[],L).
sort([Head1|Tail1],[Head2|Tail2],L) :-
Head1 < Head2 -> append([Head1],L,L2), sort(Tail1,[Head2|Tail2],L2) ;
Head1 > Head2 -> append([Head2],L,L2), sort([Head1|Tail1],Tail2,L2) ;
Head1 == Head2 -> append([Head1],L,L2), append([Head2],L2,L3),
sort(Tail1,Tail2,L3).
答案 0 :(得分:3)
您应该稍微简化一下代码:
sort([],L,L).
sort(L,[],L).
sort([Head1|Tail1], [Head2|Tail2], L) :-
Head1 < Head2 -> L = [Head1|R], sort(Tail1,[Head2|Tail2],R) ;
Head1 > Head2 -> L = [Head2|R], sort([Head1|Tail1],Tail2,R) ;
L = [Head1,Head2|R], sort(Tail1,Tail2,R).
试验:
?- sort([1,2,4,5,18],[1,3,5,10],R).
R = [1, 2, 3, 4, 5, 10, 18] .
命名这样的谓词 sort 确实会产生误导, merge 会好得多....
编辑 L = [Head1,Head2|R]
而不是L = [Head1|R]
,其中Head1 = Head2(之前的测试失败)与sort / 2 Prolog语义不同,删除了重复项。
答案 1 :(得分:2)
在SWI Prolog中,有merge/3
内置谓词就是这样做的。所以你不应该把你的谓词称为“排序”;不是。这是“合并”。
接下来,让我们阅读你的定义。
merge([H1|T1], [H2|T2], L) :-
表示合并两个列表会生成合并列表L
。到目前为止,非常好。
H1 < H2 -> append([H1],L,L2), merge(T1,[H2|T2],L2)
表示,如果H1 < H2
为答案列表添加前缀 L
H1
,则会L2
,这是合并的结果。等等,什么?那有意义吗?
Prolog不是基本的。我们写的不是“命令”来“做”东西(好吧,它们是,但是以迂回的方式)。如果我们想说H1
是L
的首要元素,我们会说:
L = [H1|L2], merge(T1,[H2|T2],L2)
%% or: append([H1],L2,L),
等。现在这是有道理的。 :)
答案 2 :(得分:1)
从您问题中的代码中提示,您正在合并已排序的数字列表。 如果这些数字都是整数,并且如果您的Prolog系统提供clpfd,请考虑使用此处提供的代码。为什么呢?
sorted1_sorted2_merged/3
表现得像真实的关系。sort/2
不同,此代码保留所有重复项(完全相同的多重性)。sorted1_sorted2_merged([1,3,5],[2,4,5,6],Zs)
等目标一样。没有任何进一步的麻烦...这是代码:
:- use_module(library(clpfd)).
sorted1_sorted2_merged([] ,Ys,Ys).
sorted1_sorted2_merged([X|Xs],Ys,Zs) :-
sorted2_hd1_tl1_merged(Ys,X,Xs,Zs).
hd1_tl1_hd2_tl2_merged(X,Xs,Y,Ys,Zs) :-
zcompare(Op,X,Y),
op_hd1_tl1_hd2_tl2_merged(Op,X,Xs,Y,Ys,Zs).
sorted1_hd2_tl2_merged([] ,Y,Ys,[Y|Ys]).
sorted1_hd2_tl2_merged([X|Xs],Y,Ys,Zs) :-
hd1_tl1_hd2_tl2_merged(X,Xs,Y,Ys,Zs).
sorted2_hd1_tl1_merged([] ,X,Xs,[X|Xs]).
sorted2_hd1_tl1_merged([Y|Ys],X,Xs,Zs) :-
hd1_tl1_hd2_tl2_merged(X,Xs,Y,Ys,Zs).
op_hd1_tl1_hd2_tl2_merged(<,X,Xs,Y,Ys,[X|Zs]) :-
sorted1_hd2_tl2_merged(Xs,Y,Ys,Zs).
op_hd1_tl1_hd2_tl2_merged(=,X,Xs,Y,Ys,[X|Zs]) :-
sorted1_hd2_tl2_merged(Xs,Y,Ys,Zs).
op_hd1_tl1_hd2_tl2_merged(>,X,Xs,Y,Ys,[Y|Zs]) :-
sorted1_hd2_tl2_merged(Ys,X,Xs,Zs).
对一些疑问!第一:
?- sorted1_sorted2_merged([1,3,4,6],[2,4,5,5,7],Xs).
Xs = [1,2,3,4,4,5,5,6,7]. % succeeds deterministically
它是否也适用于“其他方向”?
?- sorted1_sorted2_merged([1,3,4,6],Ys,[1,2,3,4,4,5,5,6,7]).
Ys = [2,4,5,5,7] ; % succeeds, but leaves behind choicepoint
false.
?- sorted1_sorted2_merged(Xs,[2,4,5,5,7],[1,2,3,4,4,5,5,6,7]).
Xs = [1,3,4,6] ; % succeeds, but leaves behind choicepoint
false.
最后,一个非常普遍的用途:
?- sorted1_sorted2_merged(Xs,Ys,[0,1,2,3]).
Xs = [ ], Ys = [0,1,2,3] ;
Xs = [0,1,2,3], Ys = [ ] ;
Xs = [0 ], Ys = [ 1,2,3] ;
Xs = [0,1 ], Ys = [ 2,3] ;
Xs = [0,1,2 ], Ys = [ 3] ;
Xs = [0,1, 3], Ys = [ 2] ;
Xs = [0, 2,3], Ys = [ 1] ;
Xs = [0, 3], Ys = [ 1,2 ] ;
Xs = [0, 2 ], Ys = [ 1, 3] ;
Xs = [ 1,2,3], Ys = [0 ] ;
Xs = [ 2,3], Ys = [0,1 ] ;
Xs = [ 3], Ys = [0,1,2 ] ;
Xs = [ 2 ], Ys = [0,1, 3] ;
Xs = [ 1 ], Ys = [0, 2,3] ;
Xs = [ 1,2 ], Ys = [0, 3] ;
Xs = [ 1, 3], Ys = [0, 2 ] ;
false.