1 ! Copyright (C) 2009 Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel sequences binary-search accessors math.order
4 specialized-arrays.uint make grouping math arrays
5 sorting assocs locals combinators fry hints ;
7 ! Sets of positive integers
9 TUPLE: interval-set { array uint-array read-only } ;
16 : find-interval ( key interval-set -- slice )
17 array>> 2 <sliced-groups>
18 [ start <=> ] with search nip ; inline
22 : in? ( key set -- ? )
24 [ [ start ] [ end 1- ] bi between? ]
27 HINTS: in? { integer interval-set } ;
31 : spec>pairs ( sequence -- intervals )
32 [ dup number? [ dup 2array ] when ] map ;
34 : disjoint? ( node1 node2 -- ? )
35 [ end ] [ start ] bi* < ;
37 : (delete-redundancies) ( seq -- )
49 : delete-redundancies ( seq -- seq' )
50 ! If the next element is >= current one, leave out both
51 [ (delete-redundancies) ] uint-array{ } make ;
53 : make-intervals ( seq -- interval-set )
58 : >intervals ( seq -- seq' )
59 [ 1+ ] assoc-map concat ;
63 : <interval-set> ( specification -- interval-set )
65 >intervals make-intervals ;
69 :: or-step ( set1 set2 -- set1' set2' )
71 set1 second set2 first <=
72 [ set1 0 ] [ set2 2 ] if
73 [ second , ] [ set2 swap tail-slice ] bi*
76 : combine-or ( set1 set2 -- )
78 { [ over empty? ] [ % drop ] }
79 { [ dup empty? ] [ drop % ] }
89 : <interval-or> ( set1 set2 -- set )
91 [ combine-or ] uint-array{ } make
96 : prefix-0 ( seq -- 0seq )
97 0 over ?nth zero? [ rest ] [ 0 prefix ] if ;
99 : interval-max ( interval-set1 interval-set2 -- n )
100 [ array>> [ 0 ] [ peek ] if-empty ] bi@ max ;
104 : <interval-not> ( set maximum -- set' )
105 [ array>> prefix-0 ] dip suffix make-intervals ;
107 : <interval-and> ( set1 set2 -- set )
109 [ '[ _ <interval-not> ] bi@ <interval-or> ] keep