move unionfind to disjoint-set, clean-ups, add project-euler 186

problem 186 uses the disjoint-set algorithm
db4
Eric Mertens 2008-04-13 03:33:49 -07:00
parent 58fde2efff
commit f881ec0109
7 changed files with 113 additions and 72 deletions

View File

@ -0,0 +1,76 @@
USING: accessors arrays hints kernel locals math sequences ;
IN: disjoint-set
<PRIVATE
TUPLE: disjoint-set parents ranks counts ;
: count ( a disjoint-set -- n )
counts>> nth ; inline
: add-count ( p a disjoint-set -- )
[ count [ + ] curry ] keep counts>> swap change-nth ; inline
: parent ( a disjoint-set -- p )
parents>> nth ; inline
: set-parent ( p a disjoint-set -- )
parents>> set-nth ; inline
: link-sets ( p a disjoint-set -- )
[ set-parent ]
[ add-count ] 3bi ; inline
: rank ( a disjoint-set -- r )
ranks>> nth ; inline
: inc-rank ( a disjoint-set -- )
ranks>> [ 1+ ] change-nth ; inline
: representative? ( a disjoint-set -- ? )
dupd parent = ; inline
: representative ( a disjoint-set -- p )
2dup representative? [ drop ] [
[ [ parent ] keep representative dup ] 2keep set-parent
] if ;
: representatives ( a b disjoint-set -- r r )
[ representative ] curry bi@ ; inline
: ranks ( a b disjoint-set -- r r )
[ rank ] curry bi@ ; inline
:: branch ( a b neg zero pos -- )
a b 2dup = [
2drop zero call
] [
< [ neg call ] [ pos call ] if
] if ; inline
PRIVATE>
: <disjoint-set> ( n -- disjoint-set )
[ >array ]
[ 0 <array> ]
[ 1 <array> ] tri
disjoint-set construct-boa ;
: equiv-set-size ( a disjoint-set -- n )
[ representative ] keep count ;
: equiv? ( a b disjoint-set -- ? )
representatives = ; inline
:: equate ( a b disjoint-set -- )
a b disjoint-set representatives
2dup = [ 2drop ] [
2dup disjoint-set ranks
[ swap ] [ over disjoint-set inc-rank ] [ ] branch
disjoint-set link-sets
] if ;
HINTS: equate disjoint-set ;
HINTS: representative disjoint-set ;
HINTS: equiv-set-size disjoint-set ;

View File

@ -0,0 +1 @@
An efficient implementation of the disjoint-set data structure

View File

@ -0,0 +1,35 @@
USING: circular disjoint-set kernel math math.ranges
sequences sequences.lib ;
IN: project-euler.186
: (generator) ( k -- n )
dup sq 300007 * 200003 - * 100003 + 1000000 rem ;
: <generator> ( -- lag )
55 [1,b] [ (generator) ] map <circular> ;
: advance ( lag -- )
[ { 0 31 } nths sum 1000000 rem ] keep push-circular ;
: next ( lag -- n )
[ first ] [ advance ] bi ;
: 2unless? ( x y ?quot quot -- )
>r 2keep rot [ 2drop ] r> if ; inline
: (p186) ( generator counter unionfind -- counter )
524287 over equiv-set-size 990000 <
[
pick [ next ] [ next ] bi
[ = ] [
pick equate
[ 1+ ] dip
] 2unless? (p186)
] [
drop nip
] if ;
: euler186 ( -- n )
<generator> 0 1000000 <disjoint-set> (p186) ;
MAIN: euler186

View File

@ -1 +1,2 @@
Aaron Schaefer
Eric Mertens

View File

@ -1 +0,0 @@
A efficient implementation of a disjoint-set datastructure

View File

@ -1,71 +0,0 @@
USING: accessors arrays combinators kernel math sequences namespaces ;
IN: unionfind
<PRIVATE
TUPLE: unionfind parents ranks counts ;
SYMBOL: uf
: count ( a -- n )
uf get counts>> nth ;
: add-count ( p a -- )
count [ + ] curry uf get counts>> swap change-nth ;
: parent ( a -- p )
uf get parents>> nth ;
: set-parent ( p a -- )
uf get parents>> set-nth ;
: link-sets ( p a -- )
[ set-parent ]
[ add-count ] 2bi ;
: rank ( a -- r )
uf get ranks>> nth ;
: inc-rank ( a -- )
uf get ranks>> [ 1+ ] change-nth ;
: topparent ( a -- p )
[ parent ] keep
2dup = [
[ topparent ] dip
2dup set-parent
] unless drop ;
PRIVATE>
: <unionfind> ( n -- unionfind )
[ >array ]
[ 0 <array> ]
[ 1 <array> ] tri
unionfind construct-boa ;
: equiv-set-size ( a uf -- n )
uf [ topparent count ] with-variable ;
: equiv? ( a b uf -- ? )
uf [ [ topparent ] bi@ = ] with-variable ;
: equate ( a b uf -- )
uf [
[ topparent ] bi@
2dup [ rank ] compare sgn
{
{ -1 [ swap link-sets ] }
{ 1 [ link-sets ] }
{ 0 [
2dup =
[ 2drop ]
[
[ link-sets ]
[ drop inc-rank ] 2bi
] if
]
}
} case
] with-variable ;