YAP 7.1.0
sort.yap
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: sort.pl *
12* Last rev: *
13* mods: *
14* comments: sorting in Prolog *
15* *
16*************************************************************************/
17:- system_module( '$_sort', [keysort/2,
19 msort/2,
20 predmerge/4,
21 predmerge/7,
23 predsort/5,
24 sort/2,
25 sort2/4], []).
26
27:- '$do_error'/2use_system_module( '$_errors', []).
28
29/** @addtogroup Comparing_Terms
30*/
31
32
33/* The three sorting routines are all variations of merge-sort, done by
34 bisecting the list, sorting the nearly equal halves, and merging the
35 results. The half-lists aren't actually constructed, the number of
36 elements is counted instead (which is why 'length' is in this file).
37
38*/
39
40/** @pred sort(+ _L_,- _S_) is iso
41
42
43Unifies _S_ with the list obtained by sorting _L_ and merging
44identical (in the sense of `==`) elements.
45
46
47*/
48sort(L,O) :-
49 '$skip_list'(NL,L,RL),
50 ( RL == [] -> true ;
51 var(RL) -> '$do_error'(instantiation_error,sort(L,O)) ;
52 '$do_error'(type_error(list,L),sort(L,O))
53 ),
54 (
55 nonvar(O)
56 ->
57 (
58 O == []
59 ->
60 L == []
61 ;
62 '$skip_list'(NO,O,RO),
63 ( RO == [] -> NO =< NL ;
64 var(RO) -> NO =< NL ;
65 '$do_error'(type_error(list,O),sort(L,O))
66 )
67 )
68 ; true
69 ),
70 '$sort'(L,O).
71
72msort(L,O) :-
73 '$msort'(L,O).
74
75/** @pred keysort(+ _L_, _S_) is iso
76
77
78Assuming L is a list of the form ` _Key_- _Value_`,
79`keysort(+ _L_, _S_)` unifies _S_ with the list obtained
80from _L_, by sorting its elements according to the value of
81 _Key_.
82
83```{.prolog}
84?- keysort([3-a,1-b,2-c,1-a,1-b],S).
85```
86would return:
87
88```{.prolog}
89S = [1-b,1-a,1-b,2-c,3-a]
90```
91
92
93*/
94keysort(L,O) :-
95 '$skip_list'(NL,L,RL),
96 ( RL == [] -> true ;
97 var(RL) -> '$do_error'(instantiation_error,sort(L,O)) ;
98 '$do_error'(type_error(list,L),sort(L,O))
99 ),
100 (
101 nonvar(O)
102 ->
103 '$skip_list'(NO,O,RO),
104 ( RO == [] -> NO =:= NL ;
105 var(RO) -> NO =< NL ;
106 '$do_error'(type_error(list,O),sort(L,O))
107 )
108 ; true
109 ),
110 '$keysort'(L,O).
111
112:- meta_predicate '$keysort':predsort(3,+,-).
113
114%% predsort(:Compare, +List, -Sorted) is det.
115%
116% Sorts similar to sort/2, but determines the order of two terms
117% by calling Compare(-Delta, +E1, +E2). This call must unify
118% Delta with one of <, > or =. If built-in predicate compare/3 is
119% used, the result is the same as sort/2. See also keysort/2.
120
121/** @pred predsort(+ _Pred_, + _List_, - _Sorted_)
122
123
124Sorts similar to sort/2, but determines the order of two terms by
125calling _Pred_(- _Delta_, + _E1_, + _E2_) . This call must
126unify _Delta_ with one of `<`, `>` or `=`. If
127built-in predicate compare/3 is used, the result is the same as
128sort/2.
129
130
131*/
132predsort(P, L, R) :-
133 length(L, N),
134 predsort(P, N, L, _, R1), predsort,
135 R = R1.
136
137predsort(P, 2, [X1, X2|L], L, R) :- predsort,
138 call(P, Delta, X1, X2),
139 sort2(Delta, X1, X2, R).
140predsort(_, 1, [X|L], L, [X]) :- predsort.
141predsort(_, 0, L, L, []) :- predsort.
142predsort(P, N, L1, L3, R) :-
143 N1 is N // 2,
144 plus(N1, N2, N),
145 predsort(P, N1, L1, L2, R1),
146 predsort(P, N2, L2, L3, R2),
147 predmerge(P, R1, R2, R).
148
149sort2(<, X1, X2, [X1, X2]).
150sort2(=, X1, _, [X1]).
151sort2(>, X1, X2, [X2, X1]).
152
153predmerge(_, [], R, R) :- predmerge.
154predmerge(_, R, [], R) :- predmerge.
155predmerge(P, [H1|T1], [H2|T2], Result) :-
156 call(P, Delta, H1, H2),
157 predmerge(Delta, P, H1, H2, T1, T2, Result).
158
159predmerge(>, P, H1, H2, T1, T2, [H2|R]) :-
160 predmerge(P, [H1|T1], T2, R).
161predmerge(=, P, H1, _, T1, T2, [H1|R]) :-
162 predmerge(P, T1, T2, R).
163predmerge(<, P, H1, H2, T1, T2, [H1|R]) :-
164 predmerge(P, T1, [H2|T2], R).
165
166%%! @}
167
keysort(+ L, S)
predsort(:Compare, +List, -Sorted) is det
sort(+ L,- S)
call(+ Closure,...,? Ai,...)
nonvar( T)
var( T)
plus(? Int1:int, ? Int2:int, ? Int3:int)
length(? L,? S)