math.combinatorics: 100%+ faster combinations.
parent
d10fd71cb3
commit
55525a8ba4
|
@ -52,24 +52,8 @@ IN: math.combinatorics.tests
|
||||||
[ "ABC" "ACB" "BAC" "BCA" "CAB" "CBA" "ABC" ]
|
[ "ABC" "ACB" "BAC" "BCA" "CAB" "CBA" "ABC" ]
|
||||||
[ "ABC" 6 [ dup dup clone-like next-permutation ] times ] unit-test
|
[ "ABC" 6 [ dup dup clone-like next-permutation ] times ] unit-test
|
||||||
|
|
||||||
[ 2598960 ] [ 52 iota 5 <combo> choose ] unit-test
|
[ { 0 1 2 } ] [ 0 3 5 combination-indices ] unit-test
|
||||||
|
[ { 2 3 4 } ] [ 9 3 5 combination-indices ] unit-test
|
||||||
[ 6 3 13 6 ] [ 7 4 28 next-values ] unit-test
|
|
||||||
[ 5 2 3 5 ] [ 6 3 13 next-values ] unit-test
|
|
||||||
[ 3 1 0 3 ] [ 5 2 3 next-values ] unit-test
|
|
||||||
[ 0 0 0 0 ] [ 3 1 0 next-values ] unit-test
|
|
||||||
|
|
||||||
[ 9 ] [ 0 5 iota 3 <combo> dual-index ] unit-test
|
|
||||||
[ 0 ] [ 9 5 iota 3 <combo> dual-index ] unit-test
|
|
||||||
[ 179 ] [ 72 10 iota 5 <combo> dual-index ] unit-test
|
|
||||||
|
|
||||||
[ { 5 3 2 1 } ] [ 7 iota 4 <combo> 8 combinadic ] unit-test
|
|
||||||
[ { 4 3 2 1 0 } ] [ 10 iota 5 <combo> 0 combinadic ] unit-test
|
|
||||||
[ { 8 6 3 1 0 } ] [ 10 iota 5 <combo> 72 combinadic ] unit-test
|
|
||||||
[ { 9 8 7 6 5 } ] [ 10 iota 5 <combo> 251 combinadic ] unit-test
|
|
||||||
|
|
||||||
[ { 0 1 2 } ] [ 0 5 iota 3 <combo> combination-indices ] unit-test
|
|
||||||
[ { 2 3 4 } ] [ 9 5 iota 3 <combo> combination-indices ] unit-test
|
|
||||||
|
|
||||||
[ { "a" "b" "c" } ] [ 0 { "a" "b" "c" "d" "e" } 3 combination ] unit-test
|
[ { "a" "b" "c" } ] [ 0 { "a" "b" "c" "d" "e" } 3 combination ] unit-test
|
||||||
[ { "c" "d" "e" } ] [ 9 { "a" "b" "c" "d" "e" } 3 combination ] unit-test
|
[ { "c" "d" "e" } ] [ 9 { "a" "b" "c" "d" "e" } 3 combination ] unit-test
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
USING: accessors arrays assocs binary-search classes.tuple fry
|
USING: accessors arrays assocs binary-search classes.tuple fry
|
||||||
kernel locals math math.order math.ranges namespaces sequences
|
kernel locals math math.order math.ranges namespaces sequences
|
||||||
sequences.private sorting ;
|
sequences.private sorting ;
|
||||||
|
FROM: sequences => change-nth ;
|
||||||
IN: math.combinatorics
|
IN: math.combinatorics
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
@ -113,61 +113,43 @@ PRIVATE>
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
TUPLE: combo
|
! "Algorithm 515: Generation of a Vector from the Lexicographical Index"
|
||||||
{ seq sequence }
|
! Buckles, B. P., and Lybanon, M. ACM
|
||||||
{ k integer } ;
|
! Transactions on Mathematical Software, Vol. 3, No. 2, June 1977.
|
||||||
|
|
||||||
C: <combo> combo
|
:: combination-indices ( x! p n -- seq )
|
||||||
|
x 1 + x!
|
||||||
|
p 0 <array> :> c 0 :> k! 0 :> r!
|
||||||
|
p 1 - [| i |
|
||||||
|
i [ 0 ] [ 1 - c nth ] if-zero i c set-nth
|
||||||
|
[ k x < ] [
|
||||||
|
i c [ 1 + ] change-nth
|
||||||
|
n i c nth - p i 1 + - nCk r!
|
||||||
|
k r + k!
|
||||||
|
] do while k r - k!
|
||||||
|
] each-integer
|
||||||
|
p 2 < [ 0 ] [ p 2 - c nth ] if
|
||||||
|
p 1 < [ drop ] [ x + k - p 1 - c set-nth ] if
|
||||||
|
c [ 1 - ] map! ;
|
||||||
|
|
||||||
: choose ( combo -- nCk )
|
:: combinations-quot ( seq k quot -- seq quot )
|
||||||
[ seq>> length ] [ k>> ] bi nCk ;
|
seq length :> n
|
||||||
|
n k nCk iota [
|
||||||
: largest-value ( a b x -- v )
|
k n combination-indices seq nths quot call
|
||||||
dup 0 = [
|
] ; inline
|
||||||
drop 1 - nip
|
|
||||||
] [
|
|
||||||
[ iota ] 2dip '[ _ nCk _ >=< ] search nip
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
:: next-values ( a b x -- a' b' x' v )
|
|
||||||
a b x largest-value dup :> v ! a'
|
|
||||||
b 1 - ! b'
|
|
||||||
x v b nCk - ! x'
|
|
||||||
v ; ! v == a'
|
|
||||||
|
|
||||||
: dual-index ( m combo -- m' )
|
|
||||||
choose 1 - swap - ;
|
|
||||||
|
|
||||||
: initial-values ( combo m -- n k m )
|
|
||||||
[ [ seq>> length ] [ k>> ] bi ] dip ;
|
|
||||||
|
|
||||||
: combinadic ( combo m -- combinadic )
|
|
||||||
initial-values [ over 0 > ] [ next-values ] produce
|
|
||||||
[ 3drop ] dip ;
|
|
||||||
|
|
||||||
:: combination-indices ( m combo -- seq )
|
|
||||||
combo m combo dual-index combinadic
|
|
||||||
combo seq>> length 1 - swap [ - ] with map! ;
|
|
||||||
|
|
||||||
: apply-combination ( m combo -- seq )
|
|
||||||
[ combination-indices ] keep seq>> nths ;
|
|
||||||
|
|
||||||
: combinations-quot ( seq k quot -- seq quot )
|
|
||||||
[ <combo> [ choose iota ] keep ] dip
|
|
||||||
'[ _ apply-combination @ ] ; inline
|
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
: combination ( m seq k -- seq' )
|
: combination ( m seq k -- seq' )
|
||||||
<combo> apply-combination ;
|
swap [ length combination-indices ] [ nths ] bi ;
|
||||||
|
|
||||||
TUPLE: combinations combo length ;
|
TUPLE: combinations seq k length ;
|
||||||
|
|
||||||
: <combinations> ( seq k -- combinations )
|
: <combinations> ( seq k -- combinations )
|
||||||
[ <combo> ] 2keep [ length ] [ nCk ] bi* combinations boa ;
|
2dup [ length ] [ nCk ] bi* combinations boa ;
|
||||||
|
|
||||||
M: combinations length length>> ; inline
|
M: combinations length length>> ; inline
|
||||||
M: combinations nth-unsafe combo>> apply-combination ;
|
M: combinations nth-unsafe [ seq>> ] [ k>> ] bi combination ;
|
||||||
M: combinations hashcode* tuple-hashcode ;
|
M: combinations hashcode* tuple-hashcode ;
|
||||||
|
|
||||||
INSTANCE: combinations immutable-sequence
|
INSTANCE: combinations immutable-sequence
|
||||||
|
|
Loading…
Reference in New Issue