js-combinatorics
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -15,3 +15,3 @@ /** | ||
*/ | ||
export const version = '1.0.0'; | ||
export const version = '1.1.0'; | ||
/** | ||
@@ -21,2 +21,7 @@ * wrapper to `BigInt`. if `BigInt` is unavailable, `Number`. | ||
const _BI = typeof BigInt == 'function' ? BigInt : Number; | ||
/** | ||
* crops BigInt | ||
*/ | ||
const _crop = n => n <= Number.MAX_SAFE_INTEGER ? Number(n) : _BI(n); | ||
; | ||
/** | ||
@@ -34,3 +39,3 @@ * calculates `P(n, k)`. | ||
while (k--) p *= n--; | ||
return p <= Number.MAX_SAFE_INTEGER ? Number(p) : p; | ||
return _crop(p); | ||
} | ||
@@ -48,3 +53,3 @@ /** | ||
const c = _BI(P(n, k)) / _BI(P(k, k)); | ||
return c <= Number.MAX_SAFE_INTEGER ? Number(c) : c; | ||
return _crop(c); | ||
} | ||
@@ -117,8 +122,28 @@ /** | ||
} | ||
/** | ||
* tells wether you need `BigInt` to access all elements. | ||
*/ | ||
get isBig() { | ||
return Number.MAX_SAFE_INTEGER < this.length; | ||
} | ||
/** | ||
* tells wether it is safe to work on this instance. | ||
* | ||
* * always `true` unless your platform does not support `BigInt`. | ||
* * if not, `true` iff `.isBig` is `false`. | ||
*/ | ||
get isSafe() { | ||
return typeof BigInt !== 'undefined' || !this.isBig; | ||
} | ||
/** | ||
* check n for nth | ||
*/ | ||
_check(n) { | ||
if (n < 0) { | ||
if (this.length < -n) throw RangeError(`${n} is too small`) | ||
return _crop(_BI(this.length) + _BI(n)); | ||
} | ||
if (this.length <= n) throw RangeError(`${n} is too large`); | ||
return n; | ||
} | ||
} | ||
@@ -141,3 +166,7 @@ /** | ||
} | ||
nth(n) { | ||
/** | ||
* @param {integer} n | ||
*/ | ||
nth(n, nocheck=false) { | ||
if (!nocheck) n = this._check(n); | ||
const offset = this.seed.length - this.size; | ||
@@ -170,3 +199,7 @@ const skip = factorial(offset); | ||
} | ||
/** | ||
* @param {integer} n | ||
*/ | ||
nth(n) { | ||
n = this._check(n); | ||
function findIndex(n) { | ||
@@ -183,3 +216,3 @@ const [one, two] | ||
} | ||
return this.perm.nth(findIndex(n)); | ||
return this.perm.nth(findIndex(n), true); | ||
} | ||
@@ -199,8 +232,10 @@ } | ||
let length = Array(size).fill(_BI(base)).reduce((a,v)=>a*v); | ||
this.length = length <= Number.MAX_SAFE_INTEGER ? Number(length) : length; | ||
this.length = _crop(length); | ||
Object.freeze(this); | ||
} | ||
/** | ||
* @param {integer} n | ||
*/ | ||
nth(n) { | ||
if (n < 0) throw RangeError(`${n} is too small`) | ||
if (this.length <= n) throw RangeError(`${n} is too large`) | ||
n = this._check(n); | ||
const base | ||
@@ -228,8 +263,12 @@ = typeof n === 'bigint' ? _BI(this.base) : this.base; | ||
const length = _BI(1) << _BI(this.seed.length) | ||
this.length = length <= Number.MAX_SAFE_INTEGER ? Number(length) : length; | ||
this.length = _crop(length); | ||
Object.freeze(this); | ||
} | ||
/** | ||
* @param {integer} n | ||
*/ | ||
nth(n) { | ||
n = this._check(n); | ||
if (n < 0) throw RangeError(`${n} is too small`) | ||
if (this.length <= n) throw RangeError(`${n} is too large`) | ||
if (this.length <= n) throw RangeError(`${n} is out of range`) | ||
const one = typeof n === 'bigint' ? _BI(1) : 1; | ||
@@ -253,8 +292,12 @@ let result = []; | ||
const length = this.seed.reduce((a,v) => a * _BI(v.length), _BI(1)) | ||
this.length = length <= Number.MAX_SAFE_INTEGER ? Number(length) : length; | ||
this.length = _crop(length); | ||
Object.freeze(this); | ||
} | ||
/** | ||
* @param {integer} n | ||
*/ | ||
nth(n) { | ||
n = this._check(n); | ||
if (n < 0) throw RangeError(`${n} is too small`) | ||
if (this.length <= n) throw RangeError(`${n} is too large`) | ||
if (this.length <= n) throw RangeError(`${n} is out of range`) | ||
let result = []; | ||
@@ -261,0 +304,0 @@ for (let i = 0; i < this.size; i++) { |
{ | ||
"name": "js-combinatorics", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Simple combinatorics like power set, combination, and permutation in JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "combinatorics.js", |
130
README.md
@@ -8,5 +8,5 @@ [![build status](https://secure.travis-ci.org/dankogai/js-combinatorics.png)](http://travis-ci.org/dankogai/js-combinatorics) | ||
# HEADS UP | ||
## HEADS UP | ||
In the next major version update, `js-combinatorics` has gone ES2015. | ||
`js-combinatorics` has gone ES2015 since version 1.1.0. | ||
@@ -52,3 +52,3 @@ * native iterator instead of custom | ||
```javascript | ||
import * as C from 'https://cdn.jsdelivr.net/npm/js-combinatorics@1.0.0/combinatorics.min.js'; | ||
import * as $C from 'https://cdn.jsdelivr.net/npm/js-combinatorics@1.1.0/combinatorics.min.js'; | ||
``` | ||
@@ -69,5 +69,45 @@ | ||
### node.js and commonjs | ||
```javascript | ||
var Combinatorics = require('js-combinatorics'); | ||
### commonjs (node.js) | ||
use [babel] or [esm]. | ||
[babel]: https://babeljs.io | ||
[esm]: https://github.com/standard-things/esm | ||
```shell | ||
% node -r esm | ||
Welcome to Node.js v14.5.0. | ||
Type ".help" for more information. | ||
> import * as $C from './combinatorics.js' | ||
undefined | ||
> $C | ||
[Module] { | ||
BaseN: [Function: BaseN], | ||
CartesianProduct: [Function: CartesianProduct], | ||
Combination: [Function: Combination], | ||
Permutation: [Function: Permutation], | ||
PowerSet: [Function: PowerSet], | ||
combination: [Function: combination], | ||
factoradic: [Function: factoradic], | ||
factorial: [Function: factorial], | ||
permutation: [Function: permutation], | ||
version: '1.1.0' | ||
} | ||
> [...new $C.Permutation('abcd')] | ||
[ | ||
[ 'a', 'b', 'c', 'd' ], [ 'a', 'b', 'd', 'c' ], | ||
[ 'a', 'c', 'b', 'd' ], [ 'a', 'c', 'd', 'b' ], | ||
[ 'a', 'd', 'b', 'c' ], [ 'a', 'd', 'c', 'b' ], | ||
[ 'b', 'a', 'c', 'd' ], [ 'b', 'a', 'd', 'c' ], | ||
[ 'b', 'c', 'a', 'd' ], [ 'b', 'c', 'd', 'a' ], | ||
[ 'b', 'd', 'a', 'c' ], [ 'b', 'd', 'c', 'a' ], | ||
[ 'c', 'a', 'b', 'd' ], [ 'c', 'a', 'd', 'b' ], | ||
[ 'c', 'b', 'a', 'd' ], [ 'c', 'b', 'd', 'a' ], | ||
[ 'c', 'd', 'a', 'b' ], [ 'c', 'd', 'b', 'a' ], | ||
[ 'd', 'a', 'b', 'c' ], [ 'd', 'a', 'c', 'b' ], | ||
[ 'd', 'b', 'a', 'c' ], [ 'd', 'b', 'c', 'a' ], | ||
[ 'd', 'c', 'a', 'b' ], [ 'd', 'c', 'b', 'a' ] | ||
] | ||
> | ||
``` | ||
@@ -153,5 +193,82 @@ | ||
```javascript | ||
it.nth(0); // [ 'a', 'b', 'c', 'd' ]; | ||
it.nth(69); // [ 'a', 'd', 'c', 'h' ]; | ||
``` | ||
`nth()` accepts both `Number` and `BigInt`. | ||
```javascript | ||
it.nth(69n); // [ 'a', 'd', 'c', 'h' ]; | ||
``` | ||
`nth()` also accepts negative indexes. In which case `n` is `(-n)th` element from `.length`. | ||
```javascript | ||
it.nth(-1); // [ 'a', 'd', 'c', 'h' ] | ||
it.nth(-70); // [ 'a', 'b', 'c', 'd' ] | ||
``` | ||
### Beyond `Number.MAX_SAFE_INTEGER` | ||
Occasionally you need `BigInt` to access elements beyond `Number.MAX_SAFE_INTEGER`. | ||
```javascript | ||
it = new $C.Permutation('abcdefghijklmnopqrstuvwxyz'); | ||
it.length; // 403291461126605635584000000n | ||
``` | ||
You can still access elements before `Number.MAX_SAFE_INTEGER` in `Number`. | ||
```javascript | ||
it.nth(0); /* [ | ||
'a', 'b', 'c', 'd', 'e', 'f', | ||
'g', 'h', 'i', 'j', 'k', 'l', | ||
'm', 'n', 'o', 'p', 'q', 'r', | ||
's', 't', 'u', 'v', 'w', 'x', | ||
'y', 'z' | ||
] */ | ||
it.nth(9007199254740990); /* [ | ||
'a', 'b', 'c', 'd', 'e', 'f', | ||
'g', 'i', 'p', 'n', 'r', 'z', | ||
'm', 'h', 'y', 'x', 'u', 't', | ||
'l', 'j', 'k', 'q', 's', 'o', | ||
'v', 'w' | ||
] */ | ||
``` | ||
But how are you goint to acccess elements beyond that? Just use `BigInt`. | ||
```javascript | ||
it.nth(9007199254740991n); /* [ | ||
'a', 'b', 'c', 'd', 'e', 'f', | ||
'g', 'i', 'p', 'n', 'r', 'z', | ||
'm', 'h', 'y', 'x', 'u', 't', | ||
'l', 'j', 'k', 'q', 's', 'o', | ||
'w', 'v' | ||
] */ | ||
it.nth(it.length - 1n); /* [ | ||
'z', 'y', 'x', 'w', 'v', 'u', | ||
't', 's', 'r', 'q', 'p', 'o', | ||
'n', 'm', 'l', 'k', 'j', 'i', | ||
'h', 'g', 'f', 'e', 'd', 'c', | ||
'b', 'a' | ||
] */ | ||
``` | ||
You can tell if you need `BigInt` via `.isBig`. | ||
```javascript | ||
new $C.Permutation('0123456789').isBig; // false | ||
new $C.Permutation('abcdefghijklmnopqrstuvwxyz').isBig; // true | ||
``` | ||
You can also check if it is safe on your platform via `.isSafe`. | ||
```javascript | ||
// true if BigInt is supported | ||
new $C.Permutation('abcdefghijklmnopqrstuvwxyz').isSafe; | ||
``` | ||
This module still runs on platforms without `BigInt` (notably Safari 13 or below), but its operation is no longer guaranteed if `.isSafe` is false. | ||
### class Permutation | ||
@@ -198,3 +315,2 @@ | ||
### class Combination | ||
@@ -201,0 +317,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
25211
302
518
0