从您问题中的代码来看,您正在合并排序的数字列表。如果这些数字都是整数并且您的 Prolog 系统提供clpfd,请考虑使用此处提供的代码。为什么?
- 该实现保留了逻辑纯度。
- 代码是单调的,使其健壮和灵活:即使在处理非地面数据时,也总是能得到逻辑上合理的答案。
- 主谓词
sorted1_sorted2_merged/3
表现得像一个真实的关系。
- 与 builtin 不同
sort/2
,此代码保留所有重复项(完全相同的多重性)。
- 关于要合并的列表中的相等项目,它的行为是合理的:输入#1 中的项目等于输入#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.