Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
js-combinatorics
Advanced tools
Simple combinatorics like power set, combination, and permutation in JavaScript
Simple combinatorics in JavaScript
In the next major version update, js-combinatorics
has gone ES2015.
import
instead of require
.BigInt
where possibleAPIs will change accordingly. Old versions are available in the version0
branch.
Check swift-combinatorics. More naturally implemented with generics and protocol.
import * as $C from 'combinatorics.js';
let it = new $C.Combination('abcdefgh', 4);
for (const elem of it) {
console.log(elem) // ['a', 'b', 'c', 'd'] ... ['a', 'd', 'e', 'f']
}
load everything…
import * as Combinatorics from 'combinatorics.js';
or just objects you want.
import {Combination, Permutation} from 'combinatorics.js';
You don't even have to install if you import
from CDNs.
import * as C from 'https://cdn.jsdelivr.net/npm/js-combinatorics@1.0.0/combinatorics.min.js';
Since this is an ES6 module, type="module"
is required the <script>
tags. of your HTML files. But you can make it globally available as follows.
<script type="module">
import * as $C from 'combinatorics.js';
window.Combinatorics = $C;
</script>
<script>
// now you can access Combinatorics
let c = new Combinatorics.Combination('abcdefgh', 4);
</script>
var Combinatorics = require('js-combinatorics');
Self-explanatory, are they not?
import {permutation, combination, factorial, factoradic} from 'combinatorics.js';
permutation(24, 12); // 1295295050649600
permutation(26, 13); // 64764752532480000n
combination(56, 28); // 7648690600760440
combination(58, 29); // 30067266499541040n
factorial(18); // 6402373705728000
factorial(19); // 121645100408832000n
factoradic(6402373705727999); // [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
factoradic(121645100408831999n) // [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
The arithmetic functions above accept both Number
and BigInt
(if supported). Return answers in Number
if it is small enough to fit within Number.MAX_SAFE_INTEGER
or BigInt
otherwise.
The module comes with Permutation
, Combination
, PowerSet
, BaseN
, and CartesianProduct
. You can individually import
them or all of them via import *
import * as $C from 'combinatorics.js';
You construct an iterable object by giving a seed iterable and options. in the example below, 'abcdefgh'
is the seed and 4
is the size of the element.
let it = new $C.Combination('abcdefgh', 4);
Once constructed, you can iterate via for … of
statement or turn it into an array via [...]
construct.
[...it]; /* [
[ 'a', 'b', 'c', 'd' ], [ 'a', 'b', 'c', 'e' ], [ 'a', 'b', 'c', 'f' ],
[ 'a', 'b', 'c', 'h' ], [ 'a', 'b', 'd', 'c' ], [ 'a', 'b', 'd', 'g' ],
[ 'a', 'b', 'd', 'e' ], [ 'a', 'b', 'd', 'h' ], [ 'a', 'b', 'e', 'd' ],
[ 'a', 'b', 'f', 'd' ], [ 'a', 'b', 'e', 'c' ], [ 'a', 'b', 'e', 'f' ],
[ 'a', 'b', 'e', 'g' ], [ 'a', 'b', 'f', 'e' ], [ 'a', 'b', 'e', 'h' ],
[ 'a', 'b', 'f', 'h' ], [ 'a', 'b', 'g', 'f' ], [ 'a', 'c', 'b', 'f' ],
[ 'a', 'b', 'f', 'g' ], [ 'a', 'b', 'g', 'c' ], [ 'a', 'b', 'g', 'd' ],
[ 'a', 'b', 'g', 'h' ], [ 'a', 'b', 'g', 'e' ], [ 'a', 'b', 'h', 'c' ],
[ 'a', 'b', 'h', 'e' ], [ 'a', 'c', 'b', 'g' ], [ 'a', 'b', 'h', 'd' ],
[ 'a', 'b', 'h', 'f' ], [ 'a', 'b', 'h', 'g' ], [ 'a', 'c', 'd', 'b' ],
[ 'a', 'c', 'b', 'd' ], [ 'a', 'c', 'd', 'h' ], [ 'a', 'c', 'f', 'e' ],
[ 'a', 'd', 'b', 'h' ], [ 'a', 'c', 'b', 'h' ], [ 'a', 'c', 'd', 'e' ],
[ 'a', 'c', 'd', 'f' ], [ 'a', 'c', 'e', 'b' ], [ 'a', 'c', 'd', 'g' ],
[ 'a', 'c', 'e', 'd' ], [ 'a', 'c', 'e', 'g' ], [ 'a', 'c', 'f', 'g' ],
[ 'a', 'c', 'e', 'f' ], [ 'a', 'c', 'e', 'h' ], [ 'a', 'c', 'f', 'b' ],
[ 'a', 'c', 'f', 'h' ], [ 'a', 'c', 'f', 'd' ], [ 'a', 'c', 'g', 'd' ],
[ 'a', 'c', 'h', 'b' ], [ 'a', 'd', 'c', 'b' ], [ 'a', 'c', 'g', 'b' ],
[ 'a', 'c', 'g', 'e' ], [ 'a', 'c', 'g', 'f' ], [ 'a', 'c', 'h', 'd' ],
[ 'a', 'c', 'g', 'h' ], [ 'a', 'c', 'h', 'e' ], [ 'a', 'c', 'h', 'g' ],
[ 'a', 'd', 'c', 'f' ], [ 'a', 'c', 'h', 'f' ], [ 'a', 'd', 'b', 'c' ],
[ 'a', 'd', 'b', 'e' ], [ 'a', 'd', 'e', 'c' ], [ 'a', 'd', 'b', 'f' ],
[ 'a', 'd', 'f', 'h' ], [ 'a', 'e', 'c', 'b' ], [ 'a', 'f', 'c', 'g' ],
[ 'a', 'd', 'c', 'e' ], [ 'a', 'd', 'c', 'g' ], [ 'a', 'd', 'c', 'h' ],
[ 'a', 'd', 'e', 'f' ]
] */
The object has .length
so you don't have to iterate to count the elements.
it.length; // 70
The object also has .nth(n)
method so you can random-access each element. This is the equivalent of subscript in Array
.
it.nth(69); // [ 'a', 'd', 'c', 'h' ];
An iterable which permutes a given iterable.
new Permutation(seed, size)
seed
: the seed iterable. [...seed]
becomes the seed array.size
: the number of elements in the iterated element. defaults to seed.length
import {Permutation} from 'combinatorics.js';
let it = new Permutation('abcd'); // size 4 is assumed4
it.length; // 24
[...it]; /* [
[ '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' ]
] */
it = new Permutation('abcdefghijklmnopqrstuvwxyz0123456789');
it.length; // 371993326789901217467999448150835200000000n
it.nth(371993326789901217467999448150835199999999n); /* [
'9', '8', '7', '6', '5', '4', '3',
'2', '1', '0', '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'
] */
An iterable which emits a combination of a given iterable.
new Combination(seed, size)
seed
: the seed iterable.size
: the number of elements in the iterated element.import {Combination} from 'combinatorics.js';
let it = new Combination('abcd', 2);
it.length; // 6
[...it]; /* [
[ 'a', 'b' ],
[ 'a', 'c' ],
[ 'a', 'd' ],
[ 'b', 'c' ],
[ 'b', 'd' ],
[ 'c', 'd' ]
] */
let a100 = Array(100).fill(0).map((v,i)=>i); // [0, 1, ...99]
it = new Combination(a100, 50);
it.length; // 100891344545564193334812497256n
it.nth(100891344545564193334812497255n); /* [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
38, 76, 36, 41, 40, 81, 84, 62, 87, 83, 43,
91, 88, 33, 34, 35, 39
] */
An iterable which emits each element of its power set.
new PowerSet(seed)
seed
: the seed iterable.import {PowerSet} from 'combinatorics.js';
let it = new PowerSet('abc');
it.length; // 8
[...it]; /* [
[],
[ 'a' ],
[ 'b' ],
[ 'a', 'b' ],
[ 'c' ],
[ 'a', 'c' ],
[ 'b', 'c' ],
[ 'a', 'b', 'c' ]
] */
it = new PowerSet(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
);
it.length; // 18446744073709551616n
it.nth(18446744073709551615n); /* [
'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', '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', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9', '+',
'/'
] */
An iterable which emits all numbers in the given system.
new BaseN(seed, size)
seed
: the seed iterable whose elements represent digits.size
: the number of digitsimport {BaseN} from 'combinatorics.js';
let it = new BaseN('abc', 3);
it.length; // 27
[...it]; /* [
[ 'a', 'a', 'a' ], [ 'b', 'a', 'a' ],
[ 'c', 'a', 'a' ], [ 'a', 'b', 'a' ],
[ 'b', 'b', 'a' ], [ 'c', 'b', 'a' ],
[ 'a', 'c', 'a' ], [ 'b', 'c', 'a' ],
[ 'c', 'c', 'a' ], [ 'a', 'a', 'b' ],
[ 'b', 'a', 'b' ], [ 'c', 'a', 'b' ],
[ 'a', 'b', 'b' ], [ 'b', 'b', 'b' ],
[ 'c', 'b', 'b' ], [ 'a', 'c', 'b' ],
[ 'b', 'c', 'b' ], [ 'c', 'c', 'b' ],
[ 'a', 'a', 'c' ], [ 'b', 'a', 'c' ],
[ 'c', 'a', 'c' ], [ 'a', 'b', 'c' ],
[ 'b', 'b', 'c' ], [ 'c', 'b', 'c' ],
[ 'a', 'c', 'c' ], [ 'b', 'c', 'c' ],
[ 'c', 'c', 'c' ]
] */
it = BaseN('0123456789abcdef', 16);
it.length; // 18446744073709551616n
it.nth(18446744073709551615n); /* [
'f', 'f', 'f', 'f',
'f', 'f', 'f', 'f',
'f', 'f', 'f', 'f',
'f', 'f', 'f', 'f'
] */
A cartesian product of given sets.
new CartesianProduct(...args)
args
: iterables that represent setsimport {CartesianProduct} from 'combinatorics.js';
let it = new CartesianProduct('012','abc','xyz');
it.length; // 27
[...it]; /* [
[ '0', 'a', 'x' ], [ '1', 'a', 'x' ],
[ '2', 'a', 'x' ], [ '0', 'b', 'x' ],
[ '1', 'b', 'x' ], [ '2', 'b', 'x' ],
[ '0', 'c', 'x' ], [ '1', 'c', 'x' ],
[ '2', 'c', 'x' ], [ '0', 'a', 'y' ],
[ '1', 'a', 'y' ], [ '2', 'a', 'y' ],
[ '0', 'b', 'y' ], [ '1', 'b', 'y' ],
[ '2', 'b', 'y' ], [ '0', 'c', 'y' ],
[ '1', 'c', 'y' ], [ '2', 'c', 'y' ],
[ '0', 'a', 'z' ], [ '1', 'a', 'z' ],
[ '2', 'a', 'z' ], [ '0', 'b', 'z' ],
[ '1', 'b', 'z' ], [ '2', 'b', 'z' ],
[ '0', 'c', 'z' ], [ '1', 'c', 'z' ],
[ '2', 'c', 'z' ]
] */
Since the number of arguments to CartesianProduct
is variable, it is sometimes helpful to give a single array with all arguments. But you cannot new ctor.apply(null, args)
this case. To mitigate that, you can use .vmake()
.
let a16 = Array(16).fill('0123456789abcdef');
it = CartesianProduct.vmake(a16);
it.length; // 18446744073709551616n
it.nth(18446744073709551615n); /* [
'f', 'f', 'f', 'f',
'f', 'f', 'f', 'f',
'f', 'f', 'f', 'f',
'f', 'f', 'f', 'f'
] */
bigCombination
is gone because all classes now can handle big -- combinatorially big! -- cases thanks to BigInt support getting standard. Safari 13 and below is a major exception but BigInt is coming to Safari 14 and up.permutationCombination
is gone because the name is misleading and it is now trivially easy to reconstruct as follow:class permutationCombination {
constructor(seed) {
this.seed = [...seed];
}
[Symbol.iterator]() {
return function*(it){
for (let i = 1, l = it.length; i <= l; i++) {
yield* new Permutation(it, i);
}
}(this.seed);
}
}
js-combinatorics
is now natively iterable. Meaning its custom iterators are gone -- with its methods like .map
and .filter
. JS iterators are very minimalistic with only [...]
and for ... of
. But don't worry. There are several ways to make those functional methods back again.For instance, You can use js-xiterable like so:
import {xiterable as $X} from
'https://cdn.jsdelivr.net/npm/js-xiterable@0.0.3/xiterable.min.js';
import {Permutation} from 'combinatorics.js';
let it = new Permutation('abcd');
let words = $X(it).map(v=>v.join(''))
for (const word of words)) console.log(word)
/*
abcd
abdc
...
dcab
dcba
*/
FAQs
Simple combinatorics like power set, combination, and permutation in JavaScript
We found that js-combinatorics demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.