1 ! Copyright (C) 2008 Eric Mertens.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays hints kernel locals math hashtables
8 { parents hashtable read-only }
9 { ranks hashtable read-only }
10 { counts hashtable read-only } ;
14 : count ( a disjoint-set -- n )
17 : add-count ( p a disjoint-set -- )
18 [ count [ + ] curry ] keep counts>> swap change-at ; inline
20 : parent ( a disjoint-set -- p )
23 : set-parent ( p a disjoint-set -- )
24 parents>> set-at ; inline
26 : link-sets ( p a disjoint-set -- )
27 [ set-parent ] [ add-count ] 3bi ; inline
29 : rank ( a disjoint-set -- r )
32 : inc-rank ( a disjoint-set -- )
33 ranks>> [ 1+ ] change-at ; inline
35 : representative? ( a disjoint-set -- ? )
36 dupd parent = ; inline
38 GENERIC: representative ( a disjoint-set -- p )
40 M: disjoint-set representative
41 2dup representative? [ drop ] [
42 [ [ parent ] keep representative dup ] 2keep set-parent
45 : representatives ( a b disjoint-set -- r r )
46 [ representative ] curry bi@ ; inline
48 : ranks ( a b disjoint-set -- r r )
49 [ rank ] curry bi@ ; inline
51 :: branch ( a b neg zero pos -- )
52 a b = zero [ a b < neg pos if ] if ; inline
56 : <disjoint-set> ( -- disjoint-set )
57 H{ } clone H{ } clone H{ } clone disjoint-set boa ;
59 GENERIC: add-atom ( a disjoint-set -- )
61 M: disjoint-set add-atom
62 [ dupd parents>> set-at ]
63 [ [ 0 ] 2dip ranks>> set-at ]
64 [ [ 1 ] 2dip counts>> set-at ]
67 : add-atoms ( seq disjoint-set -- ) '[ _ add-atom ] each ;
69 GENERIC: disjoint-set-member? ( a disjoint-set -- ? )
71 M: disjoint-set disjoint-set-member? parents>> key? ;
73 GENERIC: equiv-set-size ( a disjoint-set -- n )
75 M: disjoint-set equiv-set-size [ representative ] keep count ;
77 GENERIC: equiv? ( a b disjoint-set -- ? )
79 M: disjoint-set equiv? representatives = ;
81 GENERIC: equate ( a b disjoint-set -- )
83 M:: disjoint-set equate ( a b disjoint-set -- )
84 a b disjoint-set representatives
86 2dup disjoint-set ranks
87 [ swap ] [ over disjoint-set inc-rank ] [ ] branch
88 disjoint-set link-sets
91 : equate-all-with ( seq a disjoint-set -- )
92 '[ _ _ equate ] each ;
94 : equate-all ( seq disjoint-set -- )
95 over empty? [ 2drop ] [
96 [ unclip-slice ] dip equate-all-with
100 [ parents>> ] [ ranks>> ] [ counts>> ] tri [ clone ] tri@
103 : assoc>disjoint-set ( assoc -- disjoint-set )
105 [ '[ drop _ add-atom ] assoc-each ]
106 [ '[ _ equate ] assoc-each ]