]> gitweb.factorcode.org Git - factor.git/blob - extra/sequences/lib/lib.factor
Fix conflict
[factor.git] / extra / sequences / lib / lib.factor
1 ! Copyright (C) 2007 Slava Pestov, Chris Double, Doug Coleman,
2 !                    Eduardo Cavazos, Daniel Ehrenberg.
3 ! See http://factorcode.org/license.txt for BSD license.
4 USING: combinators.lib kernel sequences math namespaces assocs 
5 random sequences.private shuffle math.functions
6 arrays math.parser math.private sorting strings ascii macros
7 assocs.lib quotations hashtables math.order locals ;
8 IN: sequences.lib
9
10 : each-withn ( seq quot n -- ) nwith each ; inline
11
12 : each-with ( seq quot -- ) with each ; inline
13
14 : each-with2 ( obj obj list quot -- ) 2 each-withn ; inline
15
16 : map-withn ( seq quot n -- newseq ) nwith map ; inline
17
18 : map-with ( seq quot -- ) with map ; inline
19
20 : map-with2 ( obj obj list quot -- newseq ) 2 map-withn ; inline
21
22 MACRO: firstn ( n -- )
23     [ [ swap nth ] curry [ keep ] curry ] map
24     concat >quotation
25     [ drop ] compose ;
26
27 : prepare-index ( seq quot -- seq n quot )
28     >r dup length r> ; inline
29
30 : each-index ( seq quot -- )
31     #! quot: ( elt index -- )
32     prepare-index 2each ; inline
33
34 : map-index ( seq quot -- )
35     #! quot: ( elt index -- obj )
36     prepare-index 2map ; inline
37
38 : reduce-index ( seq identity quot -- )
39     #! quot: ( prev elt index -- next )
40     swapd each-index ; inline
41
42 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
43
44 : each-percent ( seq quot -- )
45   >r
46   dup length
47   dup [ / ] curry
48   [ 1+ ] prepose
49   r> compose
50   2each ;                       inline
51
52 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
53
54 : map-reduce ( seq map-quot reduce-quot -- result )
55     >r [ unclip ] dip [ call ] keep r> compose reduce ; inline
56
57 : reduce* ( seq quot -- result ) [ ] swap map-reduce ; inline
58
59 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
60
61 : higher ( a b quot -- c ) [ compare +gt+ eq? ] curry most ; inline
62
63 : lower  ( a b quot -- c ) [ compare +lt+ eq? ] curry most ; inline
64
65 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66
67 : longer  ( a b -- c ) [ length ] higher ;
68
69 : shorter ( a b -- c ) [ length ] lower ;
70
71 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
72
73 : longest ( seq -- item ) [ longer ] reduce* ;
74
75 : shortest ( seq -- item ) [ shorter ] reduce* ;
76
77 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
78
79 : bigger ( a b -- c ) [ ] higher ;
80
81 : smaller ( a b -- c ) [ ] lower ;
82
83 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
84
85 : biggest ( seq -- item ) [ bigger ] reduce* ;
86
87 : smallest ( seq -- item ) [ smaller ] reduce* ;
88
89 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
90
91 : minmax ( seq -- min max )
92     #! find the min and max of a seq in one pass
93     1/0. -1/0. rot [ tuck max >r min r> ] each ;
94
95 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
96
97 : ,, ( obj -- ) building get peek push ;
98 : v, ( -- ) V{ } clone , ;
99 : ,v ( -- ) building get dup peek empty? [ dup pop* ] when drop ;
100
101 : monotonic-split ( seq quot -- newseq )
102     [
103         >r dup unclip suffix r>
104         v, [ pick ,, call [ v, ] unless ] curry 2each ,v
105     ] { } make ;
106
107 : delete-random ( seq -- value )
108     [ length random ] keep [ nth ] 2keep delete-nth ;
109
110 : split-around ( seq quot -- before elem after )
111     dupd find over [ "Element not found" throw ] unless
112     >r cut rest r> swap ; inline
113
114 : (map-until) ( quot pred -- quot )
115     [ dup ] swap 3compose
116     [ [ drop t ] [ , f ] if ] compose [ find 2drop ] curry ;
117
118 : map-until ( seq quot pred -- newseq )
119     (map-until) { } make ;
120
121 : take-while ( seq quot -- newseq )
122     [ not ] compose
123     [ find drop [ head-slice ] when* ] curry
124     [ dup ] prepose keep like ;
125
126 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
127
128 <PRIVATE
129 : translate-string ( n alphabet out-len -- seq )
130     [ drop /mod ] with map nip  ;
131
132 : map-alphabet ( alphabet seq[seq] -- seq[seq] )
133     [ [ swap nth ] with map ] with map ;
134
135 : exact-number-strings ( n out-len -- seqs )
136     [ ^ ] 2keep [ translate-string ] 2curry map ;
137
138 : number-strings ( n max-length -- seqs )
139     1+ [ exact-number-strings ] with map concat ;
140 PRIVATE>
141
142 : exact-strings ( alphabet length -- seqs )
143     >r dup length r> exact-number-strings map-alphabet ;
144
145 : strings ( alphabet length -- seqs )
146     >r dup length r> number-strings map-alphabet ;
147
148 : switches ( seq1 seq -- subseq )
149     ! seq1 is a sequence of ones and zeroes
150     >r [ length ] keep [ nth 1 = ] curry filter r>
151     [ nth ] curry { } map-as ;
152
153 : power-set ( seq -- subsets )
154     2 over length exact-number-strings swap [ switches ] curry map ;
155
156 : push-either ( elt quot accum1 accum2 -- )
157     >r >r keep swap r> r> ? push ; inline
158
159 : 2pusher ( quot -- quot accum1 accum2 )
160     V{ } clone V{ } clone [ [ push-either ] 3curry ] 2keep ; inline
161
162 : partition ( seq quot -- trueseq falseseq )
163     over >r 2pusher >r >r each r> r> r> drop ; inline
164
165 : cut-find ( seq pred -- before after )
166     dupd find drop dup [ cut ] when ;
167
168 : cut3 ( seq pred -- first mid last )
169     [ cut-find ] keep [ not ] compose cut-find ;
170
171 : (cut-all) ( seq pred quot -- )
172     [ >r cut3 r> dip >r >r , r> [ , ] when* r> ] 2keep
173     pick [ (cut-all) ] [ 3drop ] if ;
174
175 : cut-all ( seq pred quot -- first mid last )
176     [ (cut-all) ] { } make ;
177
178 : human-sort ( seq -- newseq )
179     [ dup [ digit? ] [ string>number ] cut-all ] { } map>assoc
180     sort-values keys ;
181
182 : ?first ( seq -- first/f ) 0 swap ?nth ; inline
183 : ?second ( seq -- second/f ) 1 swap ?nth ; inline
184 : ?third ( seq -- third/f ) 2 swap ?nth ; inline
185 : ?fourth ( seq -- fourth/f ) 3 swap ?nth ; inline
186
187 : ?first2 ( seq -- 1st/f 2nd/f ) dup ?first swap ?second ; inline
188 : ?first3 ( seq -- 1st/f 2nd/f 3rd/f ) dup ?first2 rot ?third ; inline
189 : ?first4 ( seq -- 1st/f 2nd/f 3rd/f 4th/f ) dup ?first3 roll ?fourth ; inline
190
191 USE: continuations
192 : ?subseq ( from to seq -- subseq )
193     >r >r 0 max r> r>
194     [ length tuck min >r min r> ] keep subseq ;
195
196 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
197
198 ! List the positions of obj in seq
199
200 : indices ( seq obj -- seq )
201   >r dup length swap r>
202   [ = [ ] [ drop f ] if ] curry
203   2map
204   sift ;
205
206 <PRIVATE
207 : (attempt-each-integer) ( i n quot -- result )
208     [
209         iterate-step roll
210         [ 3nip ] [ iterate-next (attempt-each-integer) ] if*
211     ] [ 3drop f ] if-iterate? ; inline
212 PRIVATE>
213
214 : attempt-each ( seq quot -- result )
215     (each) iterate-prep (attempt-each-integer) ; inline
216
217 : ?nth* ( n seq -- elt/f ? )
218     2dup bounds-check? [ nth-unsafe t ] [ 2drop f f ] if ; flushable
219
220 : nths ( seq indices -- seq' )
221     swap [ nth ] curry map ;
222
223 : replace ( str oldseq newseq -- str' )
224     zip >hashtable substitute ;
225
226 : remove-nth ( seq n -- seq' )
227     cut-slice rest-slice append ;
228
229 : if-seq ( seq quot1 quot2 -- )
230     [ f like ] 2dip if* ; inline
231
232 : if-empty ( seq quot1 quot2 -- )
233     swap if-seq ; inline