factor/core/sets/sets.factor

183 lines
3.9 KiB
Factor
Raw Normal View History

2010-02-26 16:01:01 -05:00
! Copyright (C) 2010 Daniel Ehrenberg
! See http://factorcode.org/license.txt for BSD license.
USING: assocs hashtables kernel math sequences vectors ;
FROM: assocs => change-at ;
IN: sets
2010-02-26 16:01:01 -05:00
! Set protocol
MIXIN: set
GENERIC: adjoin ( elt set -- )
2013-03-23 19:56:35 -04:00
GENERIC: ?adjoin ( elt set -- ? )
2010-02-26 16:01:01 -05:00
GENERIC: in? ( elt set -- ? )
GENERIC: delete ( elt set -- )
GENERIC: set-like ( set exemplar -- set' )
GENERIC: fast-set ( set -- set' )
GENERIC: members ( set -- seq )
2010-02-26 16:01:01 -05:00
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 -- ? )
2010-02-27 00:27:40 -05:00
GENERIC: duplicates ( set -- seq )
2010-02-26 16:01:01 -05:00
GENERIC: all-unique? ( set -- ? )
GENERIC: null? ( set -- ? )
2010-12-27 22:22:36 -05:00
GENERIC: cardinality ( set -- n )
2013-03-07 21:48:15 -05:00
GENERIC: clear-set ( set -- )
2010-12-27 22:22:36 -05:00
2013-03-23 17:46:54 -04:00
M: f members drop f ;
2010-12-27 22:22:36 -05:00
M: f cardinality drop 0 ;
2010-02-26 16:01:01 -05:00
2013-03-09 01:26:56 -05:00
M: f delete 2drop ;
2013-03-07 21:48:15 -05:00
M: f clear-set drop ; inline
2010-02-26 16:01:01 -05:00
! Defaults for some methods.
! Override them for efficiency
2013-03-23 19:56:35 -04:00
M: set ?adjoin 2dup in? [ 2drop f ] [ adjoin t ] if ;
M: set null? members null? ; inline
2010-12-27 22:22:36 -05:00
M: set cardinality members length ;
2013-03-07 21:48:15 -05:00
M: set clear-set [ members ] keep [ delete ] curry each ;
2010-02-27 00:27:40 -05:00
M: set set-like drop ; inline
<PRIVATE
: ?members ( set -- seq )
dup sequence? [ members ] unless ; inline
: (union) ( set1 set2 -- seq )
[ ?members ] bi@ append ; inline
PRIVATE>
2010-02-26 16:01:01 -05:00
M: set union
[ (union) ] keep set-like ;
2008-05-25 20:44:37 -04:00
2010-02-26 16:01:01 -05:00
<PRIVATE
2010-02-26 16:01:01 -05:00
: tester ( set -- quot )
fast-set [ in? ] curry ; inline
2008-05-25 20:44:37 -04:00
2010-02-26 16:01:01 -05:00
: sequence/tester ( set1 set2 -- set1' quot )
[ members ] [ tester ] bi* ; inline
: small/large ( set1 set2 -- set1' set2' )
2dup [ cardinality ] bi@ > [ swap ] when ;
2010-02-26 16:01:01 -05:00
PRIVATE>
2010-02-26 16:01:01 -05:00
M: set intersect
[ small/large sequence/tester filter ] keep set-like ;
2010-02-26 16:01:01 -05:00
M: set diff
[ sequence/tester [ not ] compose filter ] keep set-like ;
2010-02-26 16:01:01 -05:00
M: set intersects?
small/large sequence/tester any? ;
2010-02-26 16:01:01 -05:00
<PRIVATE
: (subset?) ( set1 set2 -- ? )
sequence/tester all? ; inline
PRIVATE>
2010-02-26 16:01:01 -05:00
M: set subset?
2dup [ cardinality ] bi@ > [ 2drop f ] [ (subset?) ] if ;
2010-12-27 22:22:36 -05:00
2010-02-26 16:01:01 -05:00
M: set set=
2dup [ cardinality ] bi@ eq? [ (subset?) ] [ 2drop f ] if ;
2010-02-26 16:01:01 -05:00
M: set fast-set ;
2010-02-26 16:01:01 -05:00
M: set duplicates drop f ;
M: set all-unique? drop t ;
<PRIVATE
2013-03-23 17:46:54 -04:00
: (pruned) ( elt set accum -- )
2013-03-23 19:56:35 -04:00
2over ?adjoin [ nip push ] [ 3drop ] if ; inline
2010-02-26 16:01:01 -05:00
: pruned ( seq -- newseq )
[ f fast-set ] [ length <vector> ] bi
[ [ (pruned) ] 2curry each ] keep ;
PRIVATE>
2010-02-26 16:01:01 -05:00
! Sequences are sets
INSTANCE: sequence set
2010-02-26 16:01:01 -05:00
M: sequence in?
member? ; inline
2010-02-26 16:01:01 -05:00
M: sequence adjoin
[ delete ] [ push ] 2bi ;
2010-02-26 16:01:01 -05:00
M: sequence delete
remove! drop ; inline
2010-02-26 16:01:01 -05:00
M: sequence set-like
[ members ] dip like ;
2010-02-26 16:01:01 -05:00
M: sequence members
[ pruned ] keep like ;
2010-12-27 22:22:36 -05:00
M: sequence null?
empty? ; inline
2010-02-26 16:01:01 -05:00
2010-12-27 22:22:36 -05:00
M: sequence cardinality
fast-set cardinality ;
2010-12-27 22:22:36 -05:00
2013-03-07 21:48:15 -05:00
M: sequence clear-set
delete-all ; inline
2011-09-17 11:11:48 -04:00
: combine ( sets -- set/f )
[ f ]
[ [ [ ?members ] map concat ] [ first ] bi set-like ]
if-empty ;
2010-02-26 16:01:01 -05:00
2013-03-08 10:57:45 -05:00
: intersection ( sets -- set/f )
[ f ] [ [ ] [ intersect ] map-reduce ] if-empty ;
2011-09-22 20:19:51 -04:00
: gather ( ... seq quot: ( ... elt -- ... elt' ) -- ... newseq )
2010-02-26 16:01:01 -05:00
map concat members ; inline
: adjoin-at ( value key assoc -- )
[ [ f fast-set ] unless* [ adjoin ] keep ] change-at ;
: within ( seq set -- subseq )
2011-10-14 13:23:52 -04:00
tester filter ;
: without ( seq set -- subseq )
2011-10-14 13:23:52 -04:00
tester [ not ] compose filter ;
2013-03-10 12:11:05 -04:00
: adjoin-all ( seq set -- )
[ adjoin ] curry each ;
2013-03-08 10:57:45 -05:00
: union! ( set1 set2 -- set1 )
2013-03-10 12:11:05 -04:00
?members over adjoin-all ;
2013-03-08 10:57:45 -05:00
2013-03-08 11:21:16 -05:00
: diff! ( set1 set2 -- set1 )
dupd sequence/tester [ dup ] prepose pick
[ delete ] curry [ [ drop ] if ] curry compose each ;
2013-03-24 19:48:45 -04:00
: intersect! ( set1 set2 -- set1 )
dupd sequence/tester [ dup ] prepose [ not ] compose pick
[ delete ] curry [ [ drop ] if ] curry compose each ;
2010-02-26 16:01:01 -05:00
! Temporarily for compatibility
: unique ( seq -- assoc )
[ dup ] H{ } map>assoc ;
: conjoin ( elt assoc -- )
dupd set-at ;
: conjoin-at ( value key assoc -- )
[ dupd ?set-at ] change-at ;