2
2
*
3
3
* Abacus
4
4
* A combinatorics library for Node/XPCOM/JS, PHP, Python
5
- * @version : 0.7.0
5
+ * @version : 0.7.5
6
6
* https://github.com/foo123/Abacus
7
7
**/
8
8
! function ( root , name , factory ) {
@@ -22,7 +22,7 @@ else if ( !(name in root) ) /* Browser/WebWorker/.. */
22
22
/* module factory */ function ModuleFactory__Abacus ( undef ) {
23
23
"use strict" ;
24
24
25
- var Abacus = { VERSION : "0.7.0 " } , PROTO = 'prototype' , CLASS = 'constructor'
25
+ var Abacus = { VERSION : "0.7.5 " } , PROTO = 'prototype' , CLASS = 'constructor'
26
26
, slice = Array . prototype . slice , HAS = Object [ PROTO ] . hasOwnProperty , toString = Object [ PROTO ] . toString
27
27
, trim_re = / ^ \s + | \s + $ / g
28
28
, trim = String . prototype . trim
@@ -663,14 +663,14 @@ function subset2binary( item, n )
663
663
{
664
664
if ( 0 > n ) return [ ] ;
665
665
var binary = array ( n , 0 , 0 ) , i , l = item . length ;
666
- for ( i = 0 ; i < l ; i ++ ) binary [ item [ i ] ] = 1 ;
666
+ for ( n = n - 1 , i = 0 ; i < l ; i ++ ) binary [ n - item [ i ] ] = 1 ;
667
667
return binary ;
668
668
}
669
669
function binary2subset ( item , n )
670
670
{
671
671
n = stdMath . min ( n || item . length , item . length ) ;
672
672
var subset = [ ] , i ;
673
- for ( i = 0 ; i < n ; i ++ ) if ( 0 < item [ i ] ) subset . push ( i ) ;
673
+ for ( n = n - 1 , i = 0 ; i <= n ; i ++ ) if ( 0 < item [ i ] ) subset . push ( n - i ) ;
674
674
return subset ;
675
675
}
676
676
function conjugatepartition ( partition , packed )
@@ -1090,19 +1090,20 @@ function next_permutation( item, N, dir, type )
1090
1090
//else last item
1091
1091
else item = null ;
1092
1092
}
1093
- else //if ( " derangement" === type || "permutation" === type )
1093
+ else //if ( ("multiset" === type) || (" derangement" === type) || ( "permutation" === type) )
1094
1094
{
1095
1095
do {
1096
1096
fixed = false ;
1097
1097
//Find the largest index k such that a[k] > a[k + 1].
1098
+ // taking into account equal elements, generates multiset permutations
1098
1099
k = n - 2 ;
1099
- while ( ( k >= 0 ) && ( item [ k ] < item [ k + 1 ] ) ) k -- ;
1100
+ while ( ( k >= 0 ) && ( item [ k ] <= item [ k + 1 ] ) ) k -- ;
1100
1101
// If no such index exists, the permutation is the last permutation.
1101
1102
if ( k >= 0 )
1102
1103
{
1103
1104
//Find the largest index kl greater than k such that a[k] > a[kl].
1104
1105
kl = n - 1 ;
1105
- while ( kl > k && item [ k ] < item [ kl ] ) kl -- ;
1106
+ while ( kl > k && item [ k ] <= item [ kl ] ) kl -- ;
1106
1107
//Swap the value of a[k] with that of a[l].
1107
1108
s = item [ k ] ; item [ k ] = item [ kl ] ; item [ kl ] = s ;
1108
1109
//Reverse the sequence from a[k + 1] up to and including the final element a[n].
@@ -1138,19 +1139,20 @@ function next_permutation( item, N, dir, type )
1138
1139
//else last item
1139
1140
else item = null ;
1140
1141
}
1141
- else //if ( " derangement" === type || "permutation" === type )
1142
+ else //if ( ("multiset" === type) || (" derangement" === type) || ( "permutation" === type) )
1142
1143
{
1143
1144
do {
1144
1145
fixed = false ;
1145
1146
//Find the largest index k such that a[k] < a[k + 1].
1147
+ // taking into account equal elements, generates multiset permutations
1146
1148
k = n - 2 ;
1147
- while ( ( k >= 0 ) && ( item [ k ] > item [ k + 1 ] ) ) k -- ;
1149
+ while ( ( k >= 0 ) && ( item [ k ] >= item [ k + 1 ] ) ) k -- ;
1148
1150
// If no such index exists, the permutation is the last permutation.
1149
1151
if ( k >= 0 )
1150
1152
{
1151
1153
//Find the largest index kl greater than k such that a[k] < a[kl].
1152
1154
kl = n - 1 ;
1153
- while ( kl > k && item [ k ] > item [ kl ] ) kl -- ;
1155
+ while ( kl > k && item [ k ] >= item [ kl ] ) kl -- ;
1154
1156
//Swap the value of a[k] with that of a[l].
1155
1157
s = item [ k ] ; item [ k ] = item [ kl ] ; item [ kl ] = s ;
1156
1158
//Reverse the sequence from a[k + 1] up to and including the final element a[n].
@@ -2493,7 +2495,8 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
2493
2495
, T : CombinatorialIterator . T
2494
2496
2495
2497
, count : function ( n , $ ) {
2496
- return $ && "tuple" === $ . type ? ( ! n || ! n [ 0 ] ? 0 : Abacus . Math . exp ( n [ 0 ] , n [ 1 ] ) ) : ( ! n || ! n . length ? 0 : Abacus . Math . product ( n ) ) ;
2498
+ var O = Abacus . Arithmetic . O ;
2499
+ return $ && "tuple" === $ . type ? ( ! n || ( 0 >= n [ 0 ] ) ? O : Abacus . Math . exp ( n [ 0 ] , n [ 1 ] ) ) : ( ! n || ! n . length ? O : Abacus . Math . product ( n ) ) ;
2497
2500
}
2498
2501
, initial : function ( dir , n , $ ) {
2499
2502
// last (0>dir) is C-symmetric of first (0<dir)
@@ -2605,33 +2608,48 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
2605
2608
constructor : function Permutation ( n , $ ) {
2606
2609
var self = this ;
2607
2610
if ( ! ( self instanceof Permutation ) ) return new Permutation ( n , $ ) ;
2608
- $ = $ || { } ; $ . type = $ . type || "permutation" ;
2611
+ $ = $ || { } ; $ . type = String ( $ . type || "permutation" ) . toLowerCase ( ) ;
2609
2612
n = n || 1 ;
2610
2613
if ( n instanceof CombinatorialIterator )
2611
2614
{
2612
2615
$ . sub = n ;
2613
2616
n = $ . sub . dimension ( ) ;
2614
2617
}
2615
2618
$ . base = $ . dimension = n ;
2616
- // random ordering for derangements is based on random generation, instead of random unranking
2617
- $ . rand = { "derangement" :1 , "involution" :1 } ;
2619
+ // random ordering for multisets / derangements / involutions
2620
+ // is based on random generation, instead of random unranking
2621
+ $ . rand = { "multiset" :1 , "derangement" :1 , "involution" :1 } ;
2622
+ if ( "multiset" === $ . type )
2623
+ $ . multiplicity = is_array ( $ . multiplicity ) && $ . multiplicity . length ? $ . multiplicity . slice ( ) : array ( n , 1 , 0 ) ;
2618
2624
CombinatorialIterator . call ( self , "Permutation" , n , $ ) ;
2619
2625
}
2620
2626
2621
2627
, __static__ : {
2622
- C : function ( item , n ) {
2623
- return conjugation ( item , - 1 ) ;
2624
- }
2628
+ C : CombinatorialIterator . C
2625
2629
, P : CombinatorialIterator . P
2626
2630
, T : CombinatorialIterator . T
2627
2631
2628
2632
, count : function ( n , $ ) {
2629
- var type = $ && $ . type ? $ . type : "permutation" ;
2630
- return "cyclic" === type ? Abacus . Arithmetic . N ( n ) : Abacus . Math . factorial ( n , "derangement" === type ?false :null ) ;
2633
+ var O = Abacus . Arithmetic . O ,
2634
+ factorial = Abacus . Math . factorial ,
2635
+ type = $ && $ . type ? $ . type : "permutation" ;
2636
+ if ( 0 >= n )
2637
+ return O ;
2638
+ else if ( "cyclic" === type )
2639
+ return Abacus . Arithmetic . N ( n ) ;
2640
+ else if ( "multiset" === type )
2641
+ return factorial ( n , $ . multiplicity ) ;
2642
+ else if ( "derangement" === type )
2643
+ return 2 > n ? O : factorial ( n , false ) ;
2644
+ else if ( "involution" === type )
2645
+ return O ;
2646
+ else //if ( "permutation" === type )
2647
+ return factorial ( n ) ;
2631
2648
}
2632
2649
, initial : function ( dir , n , $ ) {
2633
2650
// last (0>dir) is C-symmetric of first (0<dir)
2634
2651
var item , type = $ && $ . type ? $ . type : "permutation" ;
2652
+ if ( 0 >= n ) return null ;
2635
2653
if ( "cyclic" === type )
2636
2654
{
2637
2655
item = 0 > dir ? [ n - 1 ] . concat ( array ( n - 1 , 0 , 1 ) ) : array ( n , 0 , 1 ) ;
@@ -2649,17 +2667,41 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
2649
2667
item = 0 > dir ? array ( n , n - 1 , - 1 ) : array ( n , function ( i ) { return i & 1 ?i - 1 :i + 1 ; } ) ;
2650
2668
}
2651
2669
}
2670
+ else if ( "multiset" === type )
2671
+ {
2672
+ var m = $ . multiplicity , nm = m . length , ki = 0 , k ,
2673
+ dk = 1 , k0 = 0 , mk = ki < nm ? m [ ki ] : 1 ;
2674
+ if ( 0 > dir ) { dk = - 1 ; k0 = nm - 1 ; }
2675
+ k = k0 ;
2676
+ item = array ( n , function ( ) {
2677
+ if ( 0 >= mk ) { ki ++ ; k += dk ; mk = ki < nm ? m [ ki ] : 1 ; }
2678
+ mk -- ;
2679
+ return k ;
2680
+ } ) ;
2681
+ }
2652
2682
else //if ( ("involution" === type) || ("multiset" === type) || ("permutation" === type) )
2653
2683
{
2654
2684
item = 0 > dir ? array ( n , n - 1 , - 1 ) : array ( n , 0 , 1 ) ;
2655
2685
}
2656
2686
return item ;
2657
2687
}
2658
2688
, cascade : CombinatorialIterator . cascade
2659
- , dual : CombinatorialIterator . dual
2689
+ , dual : function ( item , index , n , $ ) {
2690
+ if ( null == item ) return null ;
2691
+ // some C-P-T processes at play here
2692
+ var klass = this , type = $ && $ . type ? $ . type : "permutation" ,
2693
+ order = $ && $ . order ? $ . order : 0 ,
2694
+ nm = "multiset" === type ? $ . multiplicity . length : n ,
2695
+ C = klass . C , P = klass . P , T = klass . T ;
2696
+ if ( RANDOM & order ) item = REFLECTED & order ? P ( item , n ) : item . slice ( ) ;
2697
+ else if ( MINIMAL & order ) item = REFLECTED & order ? P ( item , n ) : item . slice ( ) ;
2698
+ else if ( COLEX & order ) item = REFLECTED & order ? C ( item , nm ) : P ( C ( item , nm ) , n ) ;
2699
+ else /*if ( LEX & order )*/ item = REFLECTED & order ? P ( item , n ) : item . slice ( ) ;
2700
+ return item ;
2701
+ }
2660
2702
, succ : function ( dir , item , index , n , $ ) {
2661
2703
var type = $ && $ . type ? $ . type : "permutation" ;
2662
- if ( ( "involution" === type ) || ( "multiset" === type ) ) return null ;
2704
+ if ( "involution" === type ) return null ;
2663
2705
return next_permutation ( item , n , dir , type ) ;
2664
2706
}
2665
2707
, rand : function ( n , $ ) {
@@ -2697,7 +2739,17 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
2697
2739
} while ( fixed ) ;
2698
2740
return item ;
2699
2741
}
2700
- else if ( ( "involution" === type ) || ( "multiset" === type ) )
2742
+ else if ( "multiset" === type )
2743
+ {
2744
+ // p ~ m1!*..*mk! / n!
2745
+ var m = $ . multiplicity , nm = m . length , k = 0 , mk = m [ k ] ;
2746
+ return shuffle ( array ( n , function ( ) {
2747
+ if ( 0 >= mk ) { k ++ ; mk = k < nm ? m [ k ] : 1 ; }
2748
+ mk -- ;
2749
+ return k ;
2750
+ } ) ) ;
2751
+ }
2752
+ else if ( "involution" === type )
2701
2753
{
2702
2754
return NotImplemented ( ) ;
2703
2755
}
@@ -2881,15 +2933,16 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
2881
2933
, T : CombinatorialIterator . T
2882
2934
2883
2935
, count : function ( n , $ ) {
2884
- var type = $ && $ . type ? $ . type : "unordered" ;
2936
+ var factorial = Abacus . Math . factorial ,
2937
+ type = $ && $ . type ? $ . type : "unordered" ;
2885
2938
return "ordered+repeated" === type ? (
2886
2939
Abacus . Math . exp ( n [ 0 ] , n [ 1 ] )
2887
2940
) : ( "repeated" === type ? (
2888
- Abacus . Math . factorial ( n [ 0 ] + n [ 1 ] - 1 , n [ 1 ] )
2941
+ factorial ( n [ 0 ] + n [ 1 ] - 1 , n [ 1 ] )
2889
2942
) : ( "ordered" === type ? (
2890
- Abacus . Math . factorial ( n [ 0 ] , - n [ 1 ] )
2943
+ factorial ( n [ 0 ] , - n [ 1 ] )
2891
2944
) : (
2892
- Abacus . Math . factorial ( n [ 0 ] , n [ 1 ] )
2945
+ factorial ( n [ 0 ] , n [ 1 ] )
2893
2946
) ) ) ;
2894
2947
}
2895
2948
, initial : function ( dir , n , $ ) {
0 commit comments