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 make
5 assocs random sequences.private shuffle math.functions arrays
6 math.parser math.private sorting strings ascii macros assocs.lib
7 quotations hashtables math.order locals generalizations
8 math.ranges random fry ;
11 : each-withn ( seq quot n -- ) nwith each ; inline
13 : each-with ( seq quot -- ) with each ; inline
15 : each-with2 ( obj obj list quot -- ) 2 each-withn ; inline
17 : map-withn ( seq quot n -- newseq ) nwith map ; inline
19 : map-with ( seq quot -- ) with map ; inline
21 : map-with2 ( obj obj list quot -- newseq ) 2 map-withn ; inline
23 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
25 : each-percent ( seq quot -- )
33 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35 : reduce* ( seq quot -- result ) [ ] swap map-reduce ; inline
37 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
39 : higher ( a b quot -- c ) [ compare +gt+ eq? ] curry most ; inline
41 : lower ( a b quot -- c ) [ compare +lt+ eq? ] curry most ; inline
43 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
45 : longer ( a b -- c ) [ length ] higher ;
47 : shorter ( a b -- c ) [ length ] lower ;
49 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
51 : longest ( seq -- item ) [ longer ] reduce* ;
53 : shortest ( seq -- item ) [ shorter ] reduce* ;
55 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
57 : bigger ( a b -- c ) [ ] higher ;
59 : smaller ( a b -- c ) [ ] lower ;
61 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
63 : biggest ( seq -- item ) [ bigger ] reduce* ;
65 : smallest ( seq -- item ) [ smaller ] reduce* ;
67 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
69 : minmax ( seq -- min max )
70 #! find the min and max of a seq in one pass
71 1/0. -1/0. rot [ tuck max [ min ] dip ] each ;
73 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
75 : ,, ( obj -- ) building get peek push ;
76 : v, ( -- ) V{ } clone , ;
77 : ,v ( -- ) building get dup peek empty? [ dup pop* ] when drop ;
79 : (monotonic-split) ( seq quot -- newseq )
81 [ dup unclip suffix ] dip
82 v, [ pick ,, call [ v, ] unless ] curry 2each ,v
85 : monotonic-split ( seq quot -- newseq )
86 over empty? [ 2drop { } ] [ (monotonic-split) ] if ;
88 ERROR: element-not-found ;
89 : split-around ( seq quot -- before elem after )
90 dupd find over [ element-not-found ] unless
91 [ cut rest ] dip swap ; inline
93 : map-until ( seq quot pred -- newseq )
94 '[ [ @ dup @ [ drop t ] [ , f ] if ] find 2drop ] { } make ;
96 : take-while ( seq quot -- newseq )
98 [ find drop [ head-slice ] when* ] curry
99 [ dup ] prepose keep like ;
101 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
104 : translate-string ( n alphabet out-len -- seq )
105 [ drop /mod ] with map nip ;
107 : map-alphabet ( alphabet seq[seq] -- seq[seq] )
108 [ [ swap nth ] with map ] with map ;
110 : exact-number-strings ( n out-len -- seqs )
111 [ ^ ] 2keep [ translate-string ] 2curry map ;
113 : number-strings ( n max-length -- seqs )
114 1+ [ exact-number-strings ] with map concat ;
117 : exact-strings ( alphabet length -- seqs )
118 [ dup length ] dip exact-number-strings map-alphabet ;
120 : strings ( alphabet length -- seqs )
121 [ dup length ] dip number-strings map-alphabet ;
123 : switches ( seq1 seq -- subseq )
124 ! seq1 is a sequence of ones and zeroes
125 [ [ length ] keep [ nth 1 = ] curry filter ] dip
126 [ nth ] curry { } map-as ;
128 : power-set ( seq -- subsets )
129 2 over length exact-number-strings swap [ switches ] curry map ;
131 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
134 : (attempt-each-integer) ( i n quot -- result )
137 [ 3nip ] [ iterate-next (attempt-each-integer) ] if*
138 ] [ 3drop f ] if-iterate? ; inline recursive
141 : attempt-each ( seq quot -- result )
142 (each) iterate-prep (attempt-each-integer) ; inline
144 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
146 : randomize ( seq -- seq' )
147 dup length 1 (a,b] [ dup random pick exchange ] each ;
149 : enumerate ( seq -- seq' ) <enum> >alist ;