172 lines
3.7 KiB
Factor
172 lines
3.7 KiB
Factor
! Copyright (C) 2010 Daniel Ehrenberg
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: assocs hashtables kernel math sequences vectors ;
|
|
IN: sets
|
|
|
|
! Set protocol
|
|
MIXIN: set
|
|
|
|
GENERIC: adjoin ( elt set -- )
|
|
GENERIC: ?adjoin ( elt set -- ? )
|
|
GENERIC: in? ( elt set -- ? )
|
|
GENERIC: delete ( elt set -- )
|
|
GENERIC: ?delete ( elt set -- ? )
|
|
GENERIC: set-like ( set exemplar -- set' )
|
|
GENERIC: fast-set ( set -- set' )
|
|
GENERIC: members ( set -- seq )
|
|
GENERIC: union ( set1 set2 -- set )
|
|
GENERIC: intersect ( set1 set2 -- set )
|
|
GENERIC: intersects? ( set1 set2 -- ? )
|
|
GENERIC: diff ( set1 set2 -- set )
|
|
GENERIC: subset? ( set1 set2 -- ? )
|
|
GENERIC: set= ( set1 set2 -- ? )
|
|
GENERIC: duplicates ( set -- seq )
|
|
GENERIC: all-unique? ( set -- ? )
|
|
GENERIC: null? ( set -- ? )
|
|
GENERIC: cardinality ( set -- n )
|
|
GENERIC: clear-set ( set -- )
|
|
|
|
M: f members drop f ;
|
|
|
|
M: f cardinality drop 0 ;
|
|
|
|
M: f delete 2drop ;
|
|
|
|
M: f clear-set drop ; inline
|
|
|
|
! Defaults for some methods.
|
|
! Override them for efficiency
|
|
|
|
M: set ?adjoin 2dup in? [ 2drop f ] [ adjoin t ] if ;
|
|
|
|
M: set ?delete 2dup in? [ delete t ] [ 2drop f ] if ;
|
|
|
|
M: set null? cardinality 0 = ; inline
|
|
|
|
M: set cardinality members length ;
|
|
|
|
M: set clear-set [ members ] keep [ delete ] curry each ;
|
|
|
|
M: set set-like drop ; inline
|
|
|
|
<PRIVATE
|
|
|
|
: ?members ( set -- seq )
|
|
dup sequence? [ members ] unless ; inline
|
|
|
|
: (union) ( set1 set2 -- seq )
|
|
[ ?members ] bi@ append ; inline
|
|
|
|
PRIVATE>
|
|
|
|
M: set union [ (union) ] keep set-like ;
|
|
|
|
<PRIVATE
|
|
|
|
: tester ( set -- quot )
|
|
fast-set [ in? ] curry ; inline
|
|
|
|
: sequence/tester ( set1 set2 -- set1' quot )
|
|
[ members ] [ tester ] bi* ; inline
|
|
|
|
: small/large ( set1 set2 -- set1' set2' )
|
|
2dup [ cardinality ] bi@ > [ swap ] when ; inline
|
|
|
|
: (intersect) ( set1 set2 -- seq )
|
|
small/large sequence/tester filter ; inline
|
|
|
|
: (diff) ( set1 set2 -- seq )
|
|
sequence/tester reject ; inline
|
|
|
|
PRIVATE>
|
|
|
|
M: set intersect [ (intersect) ] keep set-like ;
|
|
|
|
M: set diff [ (diff) ] keep set-like ;
|
|
|
|
M: set intersects?
|
|
small/large sequence/tester any? ;
|
|
|
|
<PRIVATE
|
|
|
|
: (subset?) ( set1 set2 -- ? )
|
|
sequence/tester all? ; inline
|
|
|
|
PRIVATE>
|
|
|
|
M: set subset?
|
|
2dup [ cardinality ] bi@ > [ 2drop f ] [ (subset?) ] if ;
|
|
|
|
M: set set=
|
|
2dup [ cardinality ] bi@ = [ (subset?) ] [ 2drop f ] if ;
|
|
|
|
M: set fast-set ;
|
|
|
|
M: set duplicates drop f ;
|
|
|
|
M: set all-unique? drop t ;
|
|
|
|
! Sequences are sets
|
|
INSTANCE: sequence set
|
|
|
|
M: sequence in?
|
|
member? ; inline
|
|
|
|
M: sequence adjoin
|
|
[ delete ] [ push ] 2bi ;
|
|
|
|
M: sequence delete
|
|
remove! drop ; inline
|
|
|
|
M: sequence set-like
|
|
[ members ] dip like ;
|
|
|
|
M: sequence members
|
|
f fast-set [ ?adjoin ] curry filter ;
|
|
|
|
M: sequence null?
|
|
empty? ; inline
|
|
|
|
M: sequence cardinality
|
|
fast-set cardinality ;
|
|
|
|
M: sequence clear-set
|
|
delete-all ; inline
|
|
|
|
: combine ( sets -- set/f )
|
|
[ f ]
|
|
[ [ [ ?members ] map concat ] [ first ] bi set-like ]
|
|
if-empty ;
|
|
|
|
: intersection ( sets -- set/f )
|
|
[ f ] [ [ ] [ intersect ] map-reduce ] if-empty ;
|
|
|
|
: refine ( sets -- set/f )
|
|
[ f ] [ [ ] [ intersect ] map-reduce ] if-empty ;
|
|
|
|
: gather ( ... seq quot: ( ... elt -- ... elt' ) -- ... newseq )
|
|
map concat members ; inline
|
|
|
|
: adjoin-at ( value key assoc -- )
|
|
[ [ f fast-set ] unless* [ adjoin ] keep ] change-at ;
|
|
|
|
: within ( seq set -- subseq )
|
|
tester filter ;
|
|
|
|
: without ( seq set -- subseq )
|
|
tester reject ;
|
|
|
|
: adjoin-all ( seq set -- )
|
|
[ adjoin ] curry each ;
|
|
|
|
: union! ( set1 set2 -- set1 )
|
|
?members over adjoin-all ;
|
|
|
|
: diff! ( set1 set2 -- set1 )
|
|
dupd sequence/tester [ dup ] prepose pick
|
|
[ delete ] curry [ [ drop ] if ] curry compose each ;
|
|
|
|
: intersect! ( set1 set2 -- set1 )
|
|
dupd sequence/tester [ dup ] prepose [ not ] compose pick
|
|
[ delete ] curry [ [ drop ] if ] curry compose each ;
|