Fix $or
[factor/jcg.git] / unmaintained / sequences-lib / lib.factor
blob72944c09b4daa049a35ddb17d21b5801b3ccaf83
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 ;
9 IN: sequences.lib
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 -- )
26   [
27     dup length
28     dup [ / ] curry
29     [ 1+ ] prepose
30   ] dip compose
31   2each ;                       inline
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 )
80     [
81         [ dup unclip suffix ] dip
82         v, [ pick ,, call [ v, ] unless ] curry 2each ,v
83     ] { } make ;
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 )
97     [ not ] compose
98     [ find drop [ head-slice ] when* ] curry
99     [ dup ] prepose keep like ;
101 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
103 <PRIVATE
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 ;
115 PRIVATE>
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 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
133 <PRIVATE
134 : (attempt-each-integer) ( i n quot -- result )
135     [
136         iterate-step roll
137         [ 3nip ] [ iterate-next (attempt-each-integer) ] if*
138     ] [ 3drop f ] if-iterate? ; inline recursive
139 PRIVATE>
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 ;