@@ -20005,6 +20005,7 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
20005
20005
add = Arithmetic.add, sub = Arithmetic.sub, mul = Arithmetic.mul,
20006
20006
index = Arithmetic.O, J = Arithmetic.J, nd, i;
20007
20007
20008
+ if (!item) return J;
20008
20009
if ("partial" === type)
20009
20010
{
20010
20011
index = Arithmetic.num(find($.data, item, true));
@@ -20017,14 +20018,22 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
20017
20018
if ("tuple" === type)
20018
20019
{
20019
20020
nd = n[0];
20020
- if (!nd) return J;
20021
- for (n=n[1],i=0; i<nd; i++) index = add(mul(index, n), item[i]);
20021
+ if (!nd || nd !== item.length) return J;
20022
+ for (n=n[1],i=0; i<nd; i++)
20023
+ {
20024
+ if (0 > item[i] || item[i] >= n) return J;
20025
+ index = add(mul(index, n), item[i]);
20026
+ }
20022
20027
}
20023
20028
else
20024
20029
{
20025
20030
nd = n.length;
20026
- if (!nd) return J;
20027
- for (i=0; i<nd; i++) index = add(mul(index, n[i]), item[i]);
20031
+ if (!nd || nd !== item.length) return J;
20032
+ for (i=0; i<nd; i++)
20033
+ {
20034
+ if (0 > item[i] || item[i] >= n[i]) return J;
20035
+ index = add(mul(index, n[i]), item[i]);
20036
+ }
20028
20037
}
20029
20038
}
20030
20039
@@ -20089,6 +20098,14 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
20089
20098
dir = -1 === dir ? -1 : 1;
20090
20099
return 0 > dir ? igray(new Array(item.length), item, n) : gray(new Array(item.length), item, n);
20091
20100
}
20101
+ ,toGray: function(item, n) {
20102
+ dir = -1 === dir ? -1 : 1;
20103
+ return gray(new Array(item.length), item, n);
20104
+ }
20105
+ ,fromGray: function(item, n) {
20106
+ dir = -1 === dir ? -1 : 1;
20107
+ return igray(new Array(item.length), item, n);
20108
+ }
20092
20109
,inversion: function(inv) {
20093
20110
// assume inv is tensor component of dimensions: (1,2,..,n-1,n) in this order
20094
20111
var i, n = inv.length, perm = n ? [0] : [];
@@ -20216,7 +20233,7 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
20216
20233
// random ordering for derangements / involutions / connecteds
20217
20234
// is based on random generation, instead of random unranking
20218
20235
$.rand = $.rand || {};
20219
- $.rand["involution"] = 1; $.rand["connected"] = 1;
20236
+ $.rand["involution"] = 1;
20220
20237
if ("multiset" === $.type)
20221
20238
{
20222
20239
$.multiplicity = is_array($.multiplicity) && $.multiplicity.length ? $.multiplicity.slice() : array($.dimension, 1, 0);
@@ -20438,21 +20455,33 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
20438
20455
I = Arithmetic.I, J = Arithmetic.J, N, M;
20439
20456
20440
20457
n = n || item.length;
20441
- if (!item || 0 > n) return J;
20458
+ if (!item || 0 > n || n !== item.length ) return J;
20442
20459
if (0===n) return index;
20443
20460
20444
20461
item = klass.DUAL(item, n, $);
20445
20462
20446
20463
if ("cyclic"=== type)
20447
20464
{
20448
- // O(1)
20449
- index = Arithmetic.num(item[0]);
20465
+ // O(n)
20466
+ ii = item[0];
20467
+ for (i=0; i<n; i++)
20468
+ {
20469
+ x = item[(i+n-ii)%n];
20470
+ if (x !== i) return J;
20471
+ }
20472
+ index = Arithmetic.num(ii);
20450
20473
}
20451
20474
else if ("connected" === type)
20452
20475
{
20453
20476
// O(nlgn)
20454
20477
if (n === item.length)
20455
20478
{
20479
+ for (dict={},i=0; i<n; i++)
20480
+ {
20481
+ x = item[i];
20482
+ if (0 > x || x >= n || 1 === dict[x]) return J;
20483
+ dict[x] = 1;
20484
+ }
20456
20485
item = permutation2cycles(item)[0];
20457
20486
if (n !== item.length) return J;
20458
20487
k = item.indexOf(n-1);
@@ -20501,6 +20530,14 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
20501
20530
// adapted from https://github.com/WoDoInc/FindMultisetRank
20502
20531
// O(nm) ~ O(n^2) TODO construct O(nlgn) algorithm
20503
20532
M = $.multiplicity.slice();
20533
+ for (i=0; i<n; i++)
20534
+ {
20535
+ x = item[i];
20536
+ if (0 > x || x >= M.length || 0 >= M[x]) return J;
20537
+ M[x]--;
20538
+ }
20539
+ if (0 !== M.filter(function(x){return x !== 0;}).length) return J;
20540
+ M = $.multiplicity.slice();
20504
20541
N = $ && null!=$.count ? $.count : factorial(n,M);
20505
20542
for (m=n-1,i=0; i<m && Arithmetic.gt(N, I); i++)
20506
20543
{
@@ -21217,20 +21254,25 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
21217
21254
,rank: function(item, n, $) {
21218
21255
var klass = this, Arithmetic = Abacus.Arithmetic,
21219
21256
add = Arithmetic.add, sub = Arithmetic.sub,
21220
- mul = Arithmetic.mul, O = Arithmetic.O, I = Arithmetic.I,
21221
- index = O, i, c, j, k = n[1], N, binom,
21257
+ mul = Arithmetic.mul, O = Arithmetic.O, I = Arithmetic.I, J = Arithmetic.J,
21258
+ index = O, i, c, j, k = n[1], N, binom, x, dict,
21222
21259
order = $ && null!=$.order ? $.order : LEX,
21223
21260
type = $ && $.type ? $.type : "combination"/*"unordered"*/;
21224
21261
21225
- if (0 > n[0] || 0 > n[1]) return Arithmetic.J;
21262
+ if (!item || 0 > n[0] || 0 > n[1] || k !== item.length) return J;
21263
+
21226
21264
if (0===k) return O;
21227
21265
item = klass.DUAL(item, n, $);
21228
21266
21229
21267
if (("ordered+repeated" === type) || ("variation+repeated" === type) || ("repeated+variation" === type))
21230
21268
{
21231
21269
// O(k)
21232
21270
N = n[0];
21233
- for (i=0; i<k; i++) index = add(mul(index, N), item[i]);
21271
+ for (i=0; i<k; i++)
21272
+ {
21273
+ if (0 > item[i] || item[i] >= N) return J;
21274
+ index = add(mul(index, N), item[i]);
21275
+ }
21234
21276
}
21235
21277
else if (("repeated" === type) || ("combination+repeated" === type))
21236
21278
{
@@ -21241,6 +21283,7 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
21241
21283
// "Algorithms for Unranking Combinations and Other Related Choice Functions", Zbigniew Kokosi´nski 1995 (http://riad.pk.edu.pl/~zk/pubs/95-1-006.pdf)
21242
21284
// adjust the order to match MSB to LSB
21243
21285
// reverse of wikipedia article http://en.wikipedia.org/wiki/Combinatorial_number_system
21286
+ if (0 > item[i-1] || item[i-1] >= n[0] || (i<k && item[i-1] > item[i])) return J;
21244
21287
c = N-1-item[i-1]-i+1; j = k+1-i;
21245
21288
if (j <= c) index = add(index, factorial(c, j));
21246
21289
}
@@ -21251,7 +21294,13 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
21251
21294
// "Efficient Algorithms to Rank and Unrank Permutations in Lexicographic Order", Blai Bonet (http://ldc.usb.ve/~bonet/reports/AAAI08-ws10-ranking.pdf)
21252
21295
// rank(ordered) = rank(k-n-permutation)
21253
21296
// O(klgk)
21254
- N = n[0]; item = permutation2inversion(null, item, N);
21297
+ N = n[0];
21298
+ for (dict={},i=0; i<k; i++)
21299
+ {
21300
+ if (0 > item[i] || item[i] >= N || 1 === dict[item[i]]) return J;
21301
+ dict[item[i]] = 1;
21302
+ }
21303
+ item = permutation2inversion(null, item, N);
21255
21304
for (i=0; i<k; i++) index = add(mul(index, N-i), item[ i ]);
21256
21305
}
21257
21306
else//if (("combination" === type) || ("unordered" === type) || ("binary" === type))
@@ -21264,6 +21313,7 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
21264
21313
// "Algorithms for Unranking Combinations and Other Related Choice Functions", Zbigniew Kokosi´nski 1995 (http://riad.pk.edu.pl/~zk/pubs/95-1-006.pdf)
21265
21314
// adjust the order to match MSB to LSB
21266
21315
// reverse of wikipedia article http://en.wikipedia.org/wiki/Combinatorial_number_system
21316
+ if (0 > item[i-1] || item[i-1] >= N || (i<k && item[i-1] >= item[i])) return J;
21267
21317
c = N-1-item[i-1]; j = k+1-i;
21268
21318
if (j <= c) index = add(index, factorial(c, j));
21269
21319
}
@@ -21358,6 +21408,12 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
21358
21408
,binary: function(item, n, dir) {
21359
21409
return -1 === dir ? binary2subset(item, n) : subset2binary(item, n);
21360
21410
}
21411
+ ,toBinary: function(item, n) {
21412
+ return subset2binary(item, n);
21413
+ }
21414
+ ,fromBinary: function(item, n) {
21415
+ return binary2subset(item, n);
21416
+ }
21361
21417
,pick: function(a, k, type) {
21362
21418
return (0 < k) && a.length ? pick(a, k, ("ordered+repeated"!==type)&&("variation+repeated"!==type)&&("repeated+variation"!==type)&&("ordered"!==type)&&("variation"!==type), ("ordered+repeated"===type)||("variation+repeated"===type)||("repeated"===type)||("combination+repeated"===type), new Array(k)) : [];
21363
21419
}
@@ -21764,6 +21820,7 @@ Subset = Abacus.Powerset = Abacus.Subset = Class(CombinatorialIterator, {
21764
21820
{
21765
21821
item = (is_binary && !is_reflected) || (is_reflected && !is_binary) ? item.slice(n-item[n],n) : item.slice(0,item[n]);
21766
21822
}
21823
+ if ($.mindimension > item.length || $.maxdimension < item.length) return J;
21767
21824
if (0 === n)
21768
21825
{
21769
21826
index = O;
@@ -22632,6 +22689,8 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
22632
22689
{
22633
22690
item = REFLECTED & order ? item.slice(LEN-item[LEN][0],LEN) : item.slice(0,item[LEN][0]);
22634
22691
}
22692
+ if ($.mindimension > item.length || $.maxdimension < item.length) return J;
22693
+
22635
22694
//if (REFLECTED & order) item = item.slice().reverse();
22636
22695
item = klass.DUAL(item.slice(), n, $, -1);
22637
22696
@@ -22643,7 +22702,7 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
22643
22702
index = O;
22644
22703
if (W && M === W)
22645
22704
{
22646
- return null == K || stdMath.floor(n/ M) === K ? O : J;
22705
+ return ( null == K || n === K* M) && 0 === item.filter(function(x){return x !== M;}).length ? O : J;
22647
22706
}
22648
22707
for (w=0,m=0,i=0; 0<n && i<item.length; i++)
22649
22708
{
@@ -22654,15 +22713,15 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
22654
22713
if (M === x) m++;
22655
22714
n -= x;
22656
22715
}
22657
- if (0 !== n) return J;
22716
+ if (0 !== n || i !== item.length ) return J;
22658
22717
if (REVERSED & order) index = Arithmetic.sub(last, index);
22659
22718
}
22660
22719
else
22661
22720
{
22662
22721
index = last;
22663
22722
if (W)
22664
22723
{
22665
- if (M === W) return null == K || stdMath.floor(n/ M) === K ? O : J;
22724
+ if (M === W) return ( null == K || n === K* M) && 0 === item.filter(function(x){return x !== M;}).length ? O : J;
22666
22725
n -= W; if (K) K--;
22667
22726
}
22668
22727
for (i=0; 0<n && i<item.length; i++)
@@ -22673,7 +22732,7 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
22673
22732
index = Arithmetic.sub(index, M && 0 === i ? O : part_rank(n, x, W, M, K ? K-i : null));
22674
22733
n -= x;
22675
22734
}
22676
- if (0 !== n) return J;
22735
+ if (0 !== n || i !== item.length ) return J;
22677
22736
if (!(REVERSED & order)) index = Arithmetic.sub(last, index);
22678
22737
}
22679
22738
}
0 commit comments