boB Rudis 3 years ago
parent
commit
b06523b609
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 1
      R/.Rproj.user/CBF2E10B/sources/prop/INDEX
  2. 1
      R/.Rproj.user/shared/notebooks/paths
  3. 2
      README.md
  4. 28
      js/01.js
  5. 15
      js/node_modules/.package-lock.json
  6. 26
      js/node_modules/generatorics/.eslintrc.json
  7. 388
      js/node_modules/generatorics/README.md
  8. 32
      js/node_modules/generatorics/bower.json
  9. 328
      js/node_modules/generatorics/generatorics.js
  10. 39
      js/node_modules/generatorics/package.json
  11. 529
      js/node_modules/generatorics/test/index.js
  12. 27
      js/package-lock.json
  13. 5
      js/package.json

1
R/.Rproj.user/CBF2E10B/sources/prop/INDEX

@ -2,3 +2,4 @@
~%2FDevelopment%2F2020-code-advent%2FR%2F01.py="E3582989"
~%2FDevelopment%2F2020-code-advent%2FREADME.md="87542FC2"
~%2FDevelopment%2F2020-code-advent%2Finput%2F01-01.txt="22EEE1B0"
~%2FDevelopment%2F2020-code-advent%2Fjs%2F01.js="BCBA9F87"

1
R/.Rproj.user/shared/notebooks/paths

@ -2,3 +2,4 @@
/Users/hrbrmstr/Development/2020-code-advent/R/01.py="1AD9A8A4"
/Users/hrbrmstr/Development/2020-code-advent/README.md="74DC8DCF"
/Users/hrbrmstr/Development/2020-code-advent/input/01-01.txt="53BE9636"
/Users/hrbrmstr/Development/2020-code-advent/js/01.js="77D3BDB6"

2
README.md

@ -1,3 +1,3 @@
# 2020 Advent of Code
Solutions in R, Swift, Python (in the `R` dir since I'm using RStudio's Python REPL) and mebbe others
Solutions in R, Swift, javascript, Python (in the `R` dir since I'm using RStudio's Python REPL) and mebbe others

28
js/01.js

@ -0,0 +1,28 @@
// See R or Python code for the problems
// 01-01
var fs = require("fs")
var combn = require('generatorics') // npm install generatorics
input = fs.readFileSync("../input/01-01.txt", "utf-8")
.split("\n")
.map(Number)
for (var pair of combn.combination(input, 2)) {
res = pair.reduce((a, b) => a+b)
if (res == 2020) {
console.log(pair.reduce((a, b) => a*b))
break
}
}
// 01-02
for (var pair of combn.combination(input, 3)) {
res = pair.reduce((a, b) => a+b)
if (res == 2020) {
console.log(pair.reduce((a, b) => a*b))
break
}
}

15
js/node_modules/.package-lock.json

@ -0,0 +1,15 @@
{
"name": "js",
"lockfileVersion": 2,
"requires": true,
"packages": {
"node_modules/generatorics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/generatorics/-/generatorics-1.1.0.tgz",
"integrity": "sha1-aVBgu42IuQmzAXGlyz1CR2hmETg=",
"engines": {
"node": ">=6.0.0"
}
}
}
}

26
js/node_modules/generatorics/.eslintrc.json

@ -0,0 +1,26 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"never"
]
}
}

388
js/node_modules/generatorics/README.md

@ -0,0 +1,388 @@
# Generatorics
### An efficient combinatorics library for JavaScript utilizing ES2015 generators. Generate combinations, permutations, and power sets of arrays or strings.
- Node
```
npm install generatorics
```
```javascript
var G = require('generatorics');
```
- Browser
```
bower install generatorics
```
```html
<script src="file/path/to/generatorics.js"></script>
```
**Note:** This module is not transpiled for compatibility, as it degrades the performance. Check your browser/node version.
## Usage
### power set
```javascript
for (var subset of G.powerSet(['a', 'b', 'c'])) {
console.log(subset);
}
// [ ]
// [ 'a' ]
// [ 'a', 'b' ]
// [ 'a', 'b', 'c' ]
// [ 'a', 'c' ]
// [ 'b' ]
// [ 'b', 'c' ]
// [ 'c' ]
```
### permutation
```javascript
for (var perm of G.permutation(['a', 'b', 'c'], 2)) {
console.log(perm);
}
// [ 'a', 'b' ]
// [ 'a', 'c' ]
// [ 'b', 'a' ]
// [ 'b', 'c' ]
// [ 'c', 'a' ]
// [ 'c', 'b' ]
for (var perm of G.permutation(['a', 'b', 'c'])) { // assumes full length of array
console.log(perm);
}
// [ 'a', 'b', 'c' ]
// [ 'a', 'c', 'b' ]
// [ 'b', 'a', 'c' ]
// [ 'b', 'c', 'a' ]
// [ 'c', 'b', 'a' ]
// [ 'c', 'a', 'b' ]
```
### combination
```javascript
for (var comb of G.combination(['a', 'b', 'c'], 2)) {
console.log(comb);
}
// [ 'a', 'b' ]
// [ 'a', 'c' ]
// [ 'b', 'c' ]
```
For efficiency, each array being yielded is the same one being mutated on each iteration. **DO NOT** mutate the array.
```javascript
var combs = [];
for (var comb of G.combination(['a', 'b', 'c'], 2)) {
combs.push(comb);
}
console.log(combs);
// [ [ 'b', 'c' ], [ 'b', 'c' ], [ 'b', 'c' ] ]
```
You can clone if necessary, or use the [clone submodule](#clone-submodule)
### permutation of combination
```javascript
for (var perm of G.permutationCombination(['a', 'b', 'c'])) {
console.log(perm);
}
// [ ]
// [ 'a' ]
// [ 'a', 'b' ]
// [ 'a', 'b', 'c' ]
// [ 'a', 'c' ]
// [ 'a', 'c', 'b' ]
// [ 'b' ]
// [ 'b', 'a' ]
// [ 'b', 'a', 'c' ]
// [ 'b', 'c' ]
// [ 'b', 'c', 'a' ]
// [ 'c' ]
// [ 'c', 'a' ]
// [ 'c', 'a', 'b' ]
// [ 'c', 'b' ]
// [ 'c', 'b', 'a' ]
```
### cartesian product
```javascript
for (var prod of G.cartesian([0, 1, 2], [0, 10, 20], [0, 100, 200])) {
console.log(prod);
}
// [ 0, 0, 0 ], [ 0, 0, 100 ], [ 0, 0, 200 ]
// [ 0, 10, 0 ], [ 0, 10, 100 ], [ 0, 10, 200 ]
// [ 0, 20, 0 ], [ 0, 20, 100 ], [ 0, 20, 200 ]
// [ 1, 0, 0 ], [ 1, 0, 100 ], [ 1, 0, 200 ]
// [ 1, 10, 0 ], [ 1, 10, 100 ], [ 1, 10, 200 ]
// [ 1, 20, 0 ], [ 1, 20, 100 ], [ 1, 20, 200 ]
// [ 2, 0, 0 ], [ 2, 0, 100 ], [ 2, 0, 200 ]
// [ 2, 10, 0 ], [ 2, 10, 100 ], [ 2, 10, 200 ]
// [ 2, 20, 0 ], [ 2, 20, 100 ], [ 2, 20, 200 ]
```
### base N
```javascript
for (var num of G.baseN(['a', 'b', 'c'])) {
console.log(num);
}
// [ 'a', 'a', 'a' ], [ 'a', 'a', 'b' ], [ 'a', 'a', 'c' ]
// [ 'a', 'b', 'a' ], [ 'a', 'b', 'b' ], [ 'a', 'b', 'c' ]
// [ 'a', 'c', 'a' ], [ 'a', 'c', 'b' ], [ 'a', 'c', 'c' ]
// [ 'b', 'a', 'a' ], [ 'b', 'a', 'b' ], [ 'b', 'a', 'c' ]
// [ 'b', 'b', 'a' ], [ 'b', 'b', 'b' ], [ 'b', 'b', 'c' ]
// [ 'b', 'c', 'a' ], [ 'b', 'c', 'b' ], [ 'b', 'c', 'c' ]
// [ 'c', 'a', 'a' ], [ 'c', 'a', 'b' ], [ 'c', 'a', 'c' ]
// [ 'c', 'b', 'a' ], [ 'c', 'b', 'b' ], [ 'c', 'b', 'c' ]
// [ 'c', 'c', 'a' ], [ 'c', 'c', 'b' ], [ 'c', 'c', 'c' ]
```
## Clone Submodule
Each array yielded from the generator is actually the same array in memory, just mutated to have different elements. This is to avoid the unnecessary creation of a bunch of arrays, which consume memory. As a result, you get a strange result when trying to generate an array.
```javascript
var combs = G.combination(['a', 'b', 'c'], 2);
console.log([...combs]);
// [ [ 'b', 'c' ], [ 'b', 'c' ], [ 'b', 'c' ] ]
```
Instead, you can use the clone submodule.
```javascript
var combs = G.clone.combination(['a', 'b', 'c'], 2);
console.log([...combs]);
// [ [ 'a', 'b' ], [ 'a', 'c' ], [ 'b', 'c' ] ]
```
### G.clone
This submodule produces generators that yield a different array on each iteration in case you need to mutate it. The [combination](#module_G.combination), [permutation](#module_G.permutation), [powerSet](#module_G.powerSet), [permutationCombination](#module_G.permutationCombination), [baseN](#module_G.baseN), [baseNAll](#module_G.baseNAll), and [cartesian](#module_G.cartesian) methods are provided on this submodule.
## Cool things to do with ES2015 generators
```javascript
var combs = G.clone.combination([1, 2, 3], 2);
// "for-of" loop
for (let comb of combs) {
console.log(comb);
}
// generate arrays
Array.from(combs);
[...combs];
// generate sets
new Set(combs);
// spreading in function calls
console.log(...combs);
```
#### Writing a code generator? Need to produce an infinite stream of minified variable names?
No problem! Just pass in a collection of all your valid characters and start generating.
```javascript
var mininym = G.baseNAll('abcdefghijklmnopqrstuvwxyz$#')
var name = mininym.next().value.join('')
global[name] = 'some value'
```
#### Card games anyone?
```javascript
var cards = [...G.clone.cartesian('♠♥♣♦', 'A23456789JQK')];
console.log(G.shuffle(cards));
// [ [ '♦', '6' ], [ '♠', '6' ], [ '♣', '7' ], [ '♥', 'K' ],
// [ '♣', 'J' ], [ '♥', '4' ], [ '♦', '2' ], [ '♥', '9' ],
// [ '♦', 'Q' ], [ '♠', 'Q' ], [ '♠', '4' ], [ '♠', 'K' ],
// [ '♥', '3' ], [ '♥', '7' ], [ '♠', '5' ], [ '♦', '7' ],
// [ '♥', '5' ], [ '♣', 'Q' ], [ '♣', '9' ], [ '♠', 'A' ],
// [ '♣', '4' ], [ '♣', '3' ], [ '♥', 'A' ], [ '♥', '8' ],
// [ '♣', '8' ], [ '♦', '8' ], [ '♠', '8' ], [ '♣', '5' ],
// [ '♥', '2' ], [ '♥', 'Q' ], [ '♦', 'A' ], [ '♥', '6' ],
// [ '♠', '2' ], [ '♣', '6' ], [ '♠', '3' ], [ '♦', 'K' ],
// [ '♦', 'J' ], [ '♠', '7' ], [ '♥', 'J' ], [ '♦', '5' ],
// [ '♦', '9' ], [ '♦', '3' ], [ '♠', '9' ], [ '♣', '2' ],
// [ '♣', 'A' ], [ '♣', 'K' ], [ '♦', '4' ], [ '♠', 'J' ] ]
```
## Documentation
<a name="module_G"></a>
## G
* [G](#module_G)
* [.factorial(n)](#module_G.factorial) ⇒ <code>Number</code>
* [.factoradic(n)](#module_G.factoradic) ⇒ <code>Array</code>
* [.P(n, k)](#module_G.P) ⇒ <code>Number</code>
* [.C(n, k)](#module_G.C) ⇒ <code>Number</code>
* [.choices(n, k, [options])](#module_G.choices) ⇒ <code>Number</code>
* [.combination(arr, [size])](#module_G.combination) ⇒ <code>Generator</code>
* [.permutation(arr, [size])](#module_G.permutation) ⇒ <code>Generator</code>
* [.powerSet(arr)](#module_G.powerSet) ⇒ <code>Generator</code>
* [.permutationCombination(arr)](#module_G.permutationCombination) ⇒ <code>Generator</code>
* [.baseN(arr, [size])](#module_G.baseN) ⇒ <code>Generator</code>
* [.baseNAll(arr)](#module_G.baseNAll) ⇒ <code>Generator</code>
* [.cartesian(...sets)](#module_G.cartesian) ⇒ <code>Generator</code>
* [.shuffle(arr)](#module_G.shuffle) ⇒ <code>Array</code>
<a name="module_G.factorial"></a>
### G.factorial(n) ⇒ <code>Number</code>
Calculates a factorial
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Number</code> - n!
| Param | Type | Description |
| --- | --- | --- |
| n | <code>Number</code> | The number to operate the factorial on. |
<a name="module_G.factoradic"></a>
### G.factoradic(n) ⇒ <code>Array</code>
Converts a number to the factorial number system. Digits are in least significant order.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Array</code> - digits of n in factoradic in least significant order
| Param | Type | Description |
| --- | --- | --- |
| n | <code>Number</code> | Integer in base 10 |
<a name="module_G.P"></a>
### G.P(n, k) ⇒ <code>Number</code>
Calculates the number of possible permutations of "k" elements in a set of size "n".
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Number</code> - n P k
| Param | Type | Description |
| --- | --- | --- |
| n | <code>Number</code> | Number of elements in the set. |
| k | <code>Number</code> | Number of elements to choose from the set. |
<a name="module_G.C"></a>
### G.C(n, k) ⇒ <code>Number</code>
Calculates the number of possible combinations of "k" elements in a set of size "n".
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Number</code> - n C k
| Param | Type | Description |
| --- | --- | --- |
| n | <code>Number</code> | Number of elements in the set. |
| k | <code>Number</code> | Number of elements to choose from the set. |
<a name="module_G.choices"></a>
### G.choices(n, k, [options]) ⇒ <code>Number</code>
Higher level method for counting number of possible combinations of "k" elements from a set of size "n".
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Number</code> - Number of possible combinations.
| Param | Type | Description |
| --- | --- | --- |
| n | <code>Number</code> | Number of elements in the set. |
| k | <code>Number</code> | Number of elements to choose from the set. |
| [options] | <code>Object</code> | |
| options.replace | <code>Boolean</code> | Is replacement allowed after each choice? |
| options.ordered | <code>Boolean</code> | Does the order of the choices matter? |
<a name="module_G.combination"></a>
### G.combination(arr, [size]) ⇒ <code>Generator</code>
Generates all combinations of a set.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields each combination as an array
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| arr | <code>Array</code> &#124; <code>String</code> | | The set of elements. |
| [size] | <code>Number</code> | <code>arr.length</code> | Number of elements to choose from the set. |
<a name="module_G.permutation"></a>
### G.permutation(arr, [size]) ⇒ <code>Generator</code>
Generates all permutations of a set.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields each permutation as an array
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| arr | <code>Array</code> &#124; <code>String</code> | | The set of elements. |
| [size] | <code>Number</code> | <code>arr.length</code> | Number of elements to choose from the set. |
<a name="module_G.powerSet"></a>
### G.powerSet(arr) ⇒ <code>Generator</code>
Generates all possible subsets of a set (a.k.a. power set).
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields each subset as an array
| Param | Type | Description |
| --- | --- | --- |
| arr | <code>Array</code> &#124; <code>String</code> | The set of elements. |
<a name="module_G.permutationCombination"></a>
### G.permutationCombination(arr) ⇒ <code>Generator</code>
Generates the permutation of the combinations of a set.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields each permutation as an array
| Param | Type | Description |
| --- | --- | --- |
| arr | <code>Array</code> &#124; <code>String</code> | The set of elements. |
<a name="module_G.baseN"></a>
### G.baseN(arr, [size]) ⇒ <code>Generator</code>
Generates all possible "numbers" from the digits of a set.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields all digits as an array
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| arr | <code>Array</code> &#124; <code>String</code> | | The set of digits. |
| [size] | <code>Number</code> | <code>arr.length</code> | How many digits will be in the numbers. |
<a name="module_G.baseNAll"></a>
### G.baseNAll(arr) ⇒ <code>Generator</code>
Infinite generator for all possible "numbers" from a set of digits.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields all digits as an array
| Param | Type | Description |
| --- | --- | --- |
| arr | <code>Array</code> &#124; <code>String</code> | The set of digits |
<a name="module_G.cartesian"></a>
### G.cartesian(...sets) ⇒ <code>Generator</code>
Generates the cartesian product of the sets.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Generator</code> - yields each product as an array
| Param | Type | Description |
| --- | --- | --- |
| ...sets | <code>Array</code> &#124; <code>String</code> | variable number of sets of n elements. |
<a name="module_G.shuffle"></a>
### G.shuffle(arr) ⇒ <code>Array</code>
Shuffles an array in place using the Fisher–Yates shuffle.
**Kind**: static method of <code>[G](#module_G)</code>
**Returns**: <code>Array</code> - a random, unbiased perutation of arr
| Param | Type | Description |
| --- | --- | --- |
| arr | <code>Array</code> | A set of elements. |

32
js/node_modules/generatorics/bower.json

@ -0,0 +1,32 @@
{
"name": "generatorics",
"version": "1.0.5",
"description": "Combinatorics library for JavaScript using ES2015 generator functions. Generate power set, combination, and permutation.",
"main": "generatorics.js",
"authors": [
"Andrew Carlson <acarl005@g.ucla.edu>"
],
"license": "MIT",
"keywords": [
"combinatorics",
"combination",
"permutation",
"powerset",
"factoradic",
"shuffle"
],
"homepage": "https://github.com/acarl005/generatorics",
"moduleType": [
"amd",
"es6",
"globals",
"node"
],
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

328
js/node_modules/generatorics/generatorics.js

@ -0,0 +1,328 @@
/*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* References:
* http://www.ruby-doc.org/core-2.0/Array.html#method-i-combination
* http://www.ruby-doc.org/core-2.0/Array.html#method-i-permutation
*/
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory)
} else if (typeof exports === 'object') {
module.exports = factory()
} else {
root.G = factory()
}
}(this, function() {
'use strict'
/** @exports G */
const G = {
clones: false,
/**
* Calculates a factorial
* @param {Number} n - The number to operate the factorial on.
* @returns {Number} n!
*/
factorial: function factorial(n) {
for (var ans = 1; n; ans *= n--);
return ans
},
/**
* Converts a number to the factorial number system. Digits are in least significant order.
* @param {Number} n - Integer in base 10
* @returns {Array} digits of n in factoradic in least significant order
*/
factoradic: function factoradic(n) {
let radix = 1
for (var digit = 1; radix < n; radix *= ++digit);
if (radix > n) radix /= digit--
let result = [0]
for (; digit; radix /= digit--) {
result[digit] = Math.floor(n / radix)
n %= radix
}
return result
},
/**
* Calculates the number of possible permutations of "k" elements in a set of size "n".
* @param {Number} n - Number of elements in the set.
* @param {Number} k - Number of elements to choose from the set.
* @returns {Number} n P k
*/
P: function P(n, k) {
return this.factorial(n) / this.factorial(n - k)
},
/**
* Calculates the number of possible combinations of "k" elements in a set of size "n".
* @param {Number} n - Number of elements in the set.
* @param {Number} k - Number of elements to choose from the set.
* @returns {Number} n C k
*/
C: function C(n, k) {
return this.P(n, k) / this.factorial(k)
},
/**
* Higher level method for counting number of possible combinations of "k" elements from a set of size "n".
* @param {Number} n - Number of elements in the set.
* @param {Number} k - Number of elements to choose from the set.
* @param {Object} [options]
* @param {Boolean} options.replace - Is replacement allowed after each choice?
* @param {Boolean} options.ordered - Does the order of the choices matter?
* @returns {Number} Number of possible combinations.
*/
choices: function choices(n, k, options = {}) {
if (options.replace) {
if (options.ordered) {
return Math.pow(n, k)
} else {
return this.C(n + k - 1, k)
}
} else {
if (options.ordered) {
return this.P(n, k)
} else {
return this.C(n, k)
}
}
},
/**
* Generates all combinations of a set.
* @param {Array|String} arr - The set of elements.
* @param {Number} [size=arr.length] - Number of elements to choose from the set.
* @returns {Generator} yields each combination as an array
*/
combination: function* combination(arr, size = arr.length) {
let that = this
let end = arr.length - 1
let data = []
yield* combinationUtil(0, 0)
function* combinationUtil(start, index) {
if (index === size) { // Current combination is ready to be processed, yield it
return yield that.clones ? data.slice() : data // .slice() is a JS idiom for shallow cloning an array
}
// replace index with all possible elements. The condition
// "end - i + 1 >= size - index" makes sure that including one element
// at index will make a combination with remaining elements
// at remaining positions
for (let i = start; i <= end && end - i + 1 >= size - index; i++) {
data[index] = arr[i]
yield* combinationUtil(i + 1, index + 1)
}
}
},
/**
* Generates all permutations of a set.
* @param {Array|String} arr - The set of elements.
* @param {Number} [size=arr.length] - Number of elements to choose from the set.
* @returns {Generator} yields each permutation as an array
*/
permutation: function* permutation(arr, size = arr.length) {
let that = this
let len = arr.length
if (size === len) { // switch to Heap's algorithm. it's more efficient
return yield* heapsAlg(arr, that.clones)
}
let data = []
let indecesUsed = [] // permutations do not repeat elements. keep track of the indeces of the elements already used
yield* permutationUtil(0)
function* permutationUtil(index) {
if (index === size) {
return yield that.clones ? data.slice() : data
}
for (let i = 0; i < len; i++) {
if (!indecesUsed[i]) {
indecesUsed[i] = true
data[index] = arr[i]
yield *permutationUtil(index + 1)
indecesUsed[i] = false
}
}
}
},
/**
* Generates all possible subsets of a set (a.k.a. power set).
* @param {Array|String} arr - The set of elements.
* @returns {Generator} yields each subset as an array
*/
powerSet: function* powerSet(arr) {
let that = this
let len = arr.length
let data = []
yield* powerUtil(0, 0)
function* powerUtil(start, index) {
data.length = index
yield that.clones ? data.slice() : data
if (index === len) {
return
}
for (let i = start; i < len; i++) {
data[index] = arr[i]
yield* powerUtil(i + 1, index + 1)
}
}
},
/**
* Generates the permutation of the combinations of a set.
* @param {Array|String} arr - The set of elements.
* @returns {Generator} yields each permutation as an array
*/
permutationCombination: function* permutationCombination(arr) {
let that = this
let len = arr.length
let data = []
let indecesUsed = []
yield* permutationUtil(0)
function* permutationUtil(index) {
data.length = index
yield that.clones ? data.slice() : data
if (index === len) {
return
}
for (let i = 0; i < len; i++) {
if (!indecesUsed[i]) {
indecesUsed[i] = true
data[index] = arr[i]
yield *permutationUtil(index + 1)
indecesUsed[i] = false
}
}
}
},
/**
* Generates all possible "numbers" from the digits of a set.
* @param {Array|String} arr - The set of digits.
* @param {Number} [size=arr.length] - How many digits will be in the numbers.
* @returns {Generator} yields all digits as an array
*/
baseN: function* baseN(arr, size = arr.length) {
let that = this
let len = arr.length
let data = []
yield* baseNUtil(0)
function* baseNUtil(index) {
if (index === size) {
return yield that.clones ? data.slice() : data
}
for (let i = 0; i < len; i++) {
data[index] = arr[i]
yield* baseNUtil(index + 1)
}
}
},
/**
* Infinite generator for all possible "numbers" from a set of digits.
* @param {Array|String} arr - The set of digits
* @returns {Generator} yields all digits as an array
*/
baseNAll: function* permutationAll(arr) {
for (let len = 1; true; len++) {
yield* this.baseN(arr, len)
}
},
/**
* Generates the cartesian product of the sets.
* @param {...(Array|String)} sets - variable number of sets of n elements.
* @returns {Generator} yields each product as an array
*/
cartesian: function* cartesian(...sets) {
let that = this
let data = []
yield* cartesianUtil(0)
function* cartesianUtil(index) {
if (index === sets.length) {
return yield that.clones ? data.slice() : data
}
for (let i = 0; i < sets[index].length; i++) {
data[index] = sets[index][i]
yield* cartesianUtil(index + 1)
}
}
},
/**
* Shuffles an array in place using the FisherYates shuffle.
* @param {Array} arr - A set of elements.
* @returns {Array} a random, unbiased perutation of arr
*/
shuffle: function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1))
swap(arr, i, j)
}
return arr
}
}
let clone = { clones: true }
clone.combination = G.combination
clone.permutation = G.permutation
clone.powerSet = G.powerSet
clone.permutationCombination = G.permutationCombination
clone.baseN = G.baseN
clone.baseNAll = G.baseNAll
clone.cartesian = G.cartesian
G.clone = clone
/*
* More efficient alorithm for permutations of All elements in an array. Doesn't
* work for "sub-permutations", e.g. permutations of 3 elements from [1, 2, 3, 4, 5]
*/
function* heapsAlg(arr, clone) {
let size = arr.length
if (typeof arr === 'string') {
arr = arr.split('')
}
yield* heapsUtil(0)
function* heapsUtil(index) {
if (index === size) {
return yield clone ? arr.slice() : arr
}
for (let j = index; j < size; j++) {
swap(arr, index, j)
yield* heapsUtil(index + 1)
swap(arr, index, j)
}
}
}
/*
* Swaps two array elements.
*/
function swap(arr, i, j) {
let len = arr.length
if (i >= len || j >= len) {
console.warn('Swapping an array\'s elements past its length.')
}
let temp = arr[j]
arr[j] = arr[i]
arr[i] = temp
return arr
}
return G
}))

39
js/node_modules/generatorics/package.json

@ -0,0 +1,39 @@
{
"name": "generatorics",
"version": "1.1.0",
"description": "Efficient Combinatorics library for JavaScript using ES2015 generator functions. Generate power set, combination, and permutation.",
"main": "generatorics.js",
"engines": {
"node": ">=6.0.0"
},
"directories": {
"test": "test"
},
"dependencies": {},
"devDependencies": {
"chai": "^3.5.0",
"eslint": "^3.14.0",
"jsdoc-to-markdown": "^3.0.0",
"mocha": "^2.4.5"
},
"scripts": {
"lint": "eslint generatorics.js",
"test": "mocha",
"docs": "sed -n '/Documentation/q;p' README.md > README.bak.md; echo '## Documentation' >> README.bak.md; jsdoc2md generatorics.js >> README.bak.md && mv -f README.bak.md README.md"
},
"author": "Andrew Carlson <acarl005@g.ucla.edu>",
"repository": {
"type": "git",
"url": "git+https://github.com/acarl005/generatorics.git"
},
"homepage": "https://github.com/acarl005/generatorics#readme",
"license": "MIT",
"keywords": [
"combinatorics",
"combination",
"permutation",
"powerset",
"factoradic",
"shuffle"
]
}

529
js/node_modules/generatorics/test/index.js

@ -0,0 +1,529 @@
var expect = require('chai').expect
var G = require('../generatorics')
describe('Arithmetic functions', () => {
it('factorial works', () => {
expect(G.factorial(0)).to.equal(1)
expect(G.factorial(1)).to.equal(1)
expect(G.factorial(2)).to.equal(2)
expect(G.factorial(3)).to.equal(6)
expect(G.factorial(4)).to.equal(24)
expect(G.factorial(5)).to.equal(120)
})
it('factoradic works', () => {
expect(G.factoradic(0)).to.eql([ 0 ])
expect(G.factoradic(1)).to.eql([ 0, 1 ])
expect(G.factoradic(2)).to.eql([ 0, 0, 1 ])
expect(G.factoradic(3)).to.eql([ 0, 1, 1 ])
expect(G.factoradic(100)).to.eql([ 0, 0, 2, 0, 4 ])
expect(G.factoradic(1337)).to.eql([ 0, 1, 2, 2, 0, 5, 1 ])
expect(G.factoradic(9001)).to.eql([ 0, 1, 0, 0, 0, 3, 5, 1 ])
expect(G.factoradic(3958174309503149571029856012)).to.eql([ 0, 1, 0, 2, 2, 3, 5, 5, 2, 2, 3, 7, 6, 1, 12, 14, 11, 12, 18, 0, 10, 2, 21, 12, 4, 21, 9 ])
})
it('P(n,r) works', () => {
expect(G.P(10, 3)).to.equal(720)
expect(G.P(10, 1)).to.equal(10)
expect(G.P(10, 0)).to.equal(1)
expect(G.P(10, 10)).to.equal(3628800)
})
it('C(n,r) works', () => {
expect(G.C(10, 3)).to.equal(120)
expect(G.C(10, 1)).to.equal(10)
expect(G.C(10, 0)).to.equal(1)
expect(G.C(10, 10)).to.equal(1)
})
it('higher level method for counting choices', () => {
expect(G.choices(10, 3, { replace: true, ordered: true })).to.equal(1000)
expect(G.choices(10, 3, { replace: true, ordered: false })).to.equal(220)
expect(G.choices(10, 3, { replace: false, ordered: true })).to.equal(720)
expect(G.choices(10, 3, { replace: false, ordered: false })).to.equal(120)
})
})
describe('Combinations', () => {
it('should get combinations of two from set of 3', () => {
var members = [
[ 1, 2 ],
[ 1, 3 ],
[ 2, 3 ]
]
var answers = []
for (var comb of G.combination([1, 2, 3], 2)) {
answers.push(comb.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with size 1', () => {
var members = [
[ 1 ],
[ 2 ],
[ 3 ]
]
var answers = []
for (var comb of G.combination([1, 2, 3], 1)) {
answers.push(comb.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with size 0', () => {
for (var comb of G.combination([1, 2, 3], 0)) {
expect(comb).to.eql([])
}
})
it('should yield nothing if size is greater than array length', () => {
for (var comb of G.combination([1, 2, 3], 4)) {
throw new Error('Made a combination when it should not have')
}
})
it('combinations should default to arr.length without size specified', () => {
for (var comb of G.combination([1, 2, 3])) {
expect(comb).to.eql([1, 2, 3])
}
})
it('should work with strings', () => {
var members = [
[ 'a', 'b' ],
[ 'a', 'c' ],
[ 'a', 'd' ],
[ 'b', 'c' ],
[ 'b', 'd' ],
[ 'c', 'd' ],
]
var answers = []
for (var comb of G.combination('abcd', 2)) {
answers.push(comb.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('yields the same array each time', () => {
var arr = [...G.combination([1, 2, 3], 2)]
expect(arr).to.eql(Array(arr.length).fill(arr[0]))
})
})
describe('Permutations', () => {
it('should get permutations of 2 from a set of 3', () => {
var members = [
[ 1, 2 ],
[ 1, 3 ],
[ 2, 1 ],
[ 2, 3 ],
[ 3, 1 ],
[ 3, 2 ]
]
var answers = []
for (var perm of G.permutation([1, 2, 3], 2)) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with size 1', () => {
var members = [
[ 1 ],
[ 2 ],
[ 3 ]
]
var answers = []
for (var perm of G.permutation([1, 2, 3], 1)) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with size 0', () => {
for (var perm of G.permutation([1, 2, 3], 0)) {
expect(perm).to.eql([])
}
})
it('should yield nothing if size is greater than array length', () => {
for (var perm of G.permutation([1, 2, 3], 4)) {
throw new Error('Made a permutation when it should not have')
}
})
it('permutations should default to arr.length without size specified', () => {
var members = [
[ 1, 2, 3 ],
[ 1, 3, 2 ],
[ 2, 1, 3 ],
[ 2, 3, 1 ],
[ 3, 2, 1 ],
[ 3, 1, 2 ],
]
var answers = []
for (var perm of G.permutation([1, 2, 3])) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with strings', () => {
var members = [
[ 'a', 'b' ],
[ 'a', 'c' ],
[ 'a', 'd' ],
[ 'b', 'a' ],
[ 'b', 'c' ],
[ 'b', 'd' ],
[ 'c', 'a' ],
[ 'c', 'b' ],
[ 'c', 'd' ],
[ 'd', 'a' ],
[ 'd', 'b' ],
[ 'd', 'c' ],
]
var answers = []
for (var perm of G.permutation('abcd', 2)) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with string without specifying length', () => {
var members = [
[ 'a', 'b', 'c' ],
[ 'a', 'c', 'b' ],
[ 'b', 'a', 'c' ],
[ 'b', 'c', 'a' ],
[ 'c', 'b', 'a' ],
[ 'c', 'a', 'b' ]
]
var answers = []
for (var perm of G.permutation('abc')) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('yields the same array each time', () => {
var arr = [...G.permutation([1, 2, 3], 2)]
expect(arr).to.eql(Array(arr.length).fill(arr[0]))
})
})
describe('Base N', () => {
it('should get number of 2 digits a set of 3', () => {
var members = [
[ 1, 1 ],
[ 1, 2 ],
[ 1, 3 ],
[ 2, 1 ],
[ 2, 2 ],
[ 2, 3 ],
[ 3, 1 ],
[ 3, 2 ],
[ 3, 3 ],
]
var answers = []
for (var perm of G.baseN([1, 2, 3], 2)) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with size 1', () => {
var members = [
[ 1 ],
[ 2 ],
[ 3 ]
]
var answers = []
for (var perm of G.baseN([1, 2, 3], 1)) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with size 0', () => {
for (var perm of G.baseN([1, 2, 3], 0)) {
expect(perm).to.eql([])
}
})
it('baseN should default to arr.length without size specified', () => {
var members = [
[ 1, 1, 1 ],
[ 1, 1, 2 ],
[ 1, 1, 3 ],
[ 1, 2, 1 ],
[ 1, 2, 2 ],
[ 1, 2, 3 ],
[ 1, 3, 1 ],
[ 1, 3, 2 ],
[ 1, 3, 3 ],
[ 2, 1, 1 ],
[ 2, 1, 2 ],
[ 2, 1, 3 ],
[ 2, 2, 1 ],
[ 2, 2, 2 ],
[ 2, 2, 3 ],
[ 2, 3, 1 ],
[ 2, 3, 2 ],
[ 2, 3, 3 ],
[ 3, 1, 1 ],
[ 3, 1, 2 ],
[ 3, 1, 3 ],
[ 3, 2, 1 ],
[ 3, 2, 2 ],
[ 3, 2, 3 ],
[ 3, 3, 1 ],
[ 3, 3, 2 ],
[ 3, 3, 3 ],
]
var answers = []
for (var perm of G.baseN([1, 2, 3])) {
answers.push(perm.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('yields the same array each time', () => {
var arr = [...G.baseN([1, 2, 3])]
expect(arr).to.eql(Array(arr.length).fill(arr[0]))
})
})
describe('Power Set', () => {
it('should calculate power set', () => {
var members = [
[ ],
[ 1 ],
[ 2 ],
[ 1, 2 ],
[ 3 ],
[ 1, 3 ],
[ 2, 3 ],
[ 1, 2, 3 ]
]
var answers = []
for (var sett of G.powerSet([1, 2, 3])) {
answers.push(sett.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('yields the same array each time', () => {
var arr = [...G.powerSet([1, 2, 3])]
expect(arr).to.eql(Array(arr.length).fill(arr[0]))
})
})
describe('Permutation Combination', () => {
it('should get the permutation of combinations', () => {
var members = [
[ ],
[ 'a' ],
[ 'b' ],
[ 'c' ],
[ 'a', 'b' ],
[ 'b', 'a' ],
[ 'a', 'c' ],
[ 'c', 'a' ],
[ 'b', 'c' ],
[ 'c', 'b' ],
[ 'a', 'b', 'c' ],
[ 'a', 'c', 'b' ],
[ 'b', 'a', 'c' ],
[ 'b', 'c', 'a' ],
[ 'c', 'a', 'b' ],
[ 'c', 'b', 'a' ]
]
var answers = []
for (var comb of G.permutationCombination(['a', 'b', 'c'])) {
answers.push(comb.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should yield the same array each time', () => {
var arr = [...G.permutationCombination([1, 2, 3])]
expect(arr).to.eql(Array(arr.length).fill(arr[0]))
})
})
describe('Cartesian Product', () => {
it('should find the cartesian product of a bunch of arrays', () => {
var members = [
[0, 0, 0], [1, 0, 0], [2, 0, 0],
[0, 10, 0], [1, 10, 0], [2, 10, 0],
[0, 20, 0], [1, 20, 0], [2, 20, 0],
[0, 0, 100], [1, 0, 100], [2, 0, 100],
[0, 10, 100],[1, 10, 100],[2, 10, 100],
[0, 20, 100],[1, 20, 100],[2, 20, 100],
[0, 0, 200], [1, 0, 200], [2, 0, 200],
[0, 10, 200],[1, 10, 200],[2, 10, 200],
[0, 20, 200],[1, 20, 200],[2, 20, 200]
]
var answers = []
for (var sett of G.cartesian([0, 1, 2], [0, 10, 20], [0, 100, 200])) {
answers.push(sett.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with apply', () => {
var members = [
[0, 0, 0], [1, 0, 0], [2, 0, 0],
[0, 10, 0], [1, 10, 0], [2, 10, 0],
[0, 20, 0], [1, 20, 0], [2, 20, 0],
[0, 0, 100], [1, 0, 100], [2, 0, 100],
[0, 10, 100],[1, 10, 100],[2, 10, 100],
[0, 20, 100],[1, 20, 100],[2, 20, 100],
[0, 0, 200], [1, 0, 200], [2, 0, 200],
[0, 10, 200],[1, 10, 200],[2, 10, 200],
[0, 20, 200],[1, 20, 200],[2, 20, 200]
]
var answers = []
for (var sett of G.cartesian.apply(G, [[0, 1, 2], [0, 10, 20], [0, 100, 200]])) {
answers.push(sett.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should work with strings', () => {
var members = [
[ 'a', 'c', 'e' ],
[ 'a', 'c', 'f' ],
[ 'a', 'd', 'e' ],
[ 'a', 'd', 'f' ],
[ 'b', 'c', 'e' ],
[ 'b', 'c', 'f' ],
[ 'b', 'd', 'e' ],
[ 'b', 'd', 'f' ]
]
var answers = []
for (var sett of G.cartesian('ab', 'cd', 'ef')) {
answers.push(sett.slice())
}
expect(answers).to.have.length(members.length)
expect(answers).to.deep.have.members(members)
})
it('should yield same array each time', () => {
var arr = [...G.cartesian('12', '34', '56')]
expect(arr).to.eql(Array(arr.length).fill(arr[0]))
})
})
describe('Infinite Base N', () => {
it('generates all permutations of an array', () => {
var members = [
[ 'a' ], [ 'b' ], [ 'c' ], [ 'a', 'a' ], [ 'a', 'b' ], [ 'a', 'c' ], [ 'b', 'a' ], [ 'b', 'b' ], [ 'b', 'c' ], [ 'c', 'a' ], [ 'c', 'b' ], [ 'c', 'c' ],
[ 'a', 'a', 'a' ], [ 'a', 'a', 'b' ], [ 'a', 'a', 'c' ], [ 'a', 'b', 'a' ], [ 'a', 'b', 'b' ], [ 'a', 'b', 'c' ], [ 'a', 'c', 'a' ], [ 'a', 'c', 'b' ],
[ 'a', 'c', 'c' ], [ 'b', 'a', 'a' ], [ 'b', 'a', 'b' ], [ 'b', 'a', 'c' ], [ 'b', 'b', 'a' ], [ 'b', 'b', 'b' ], [ 'b', 'b', 'c' ], [ 'b', 'c', 'a' ],
[ 'b', 'c', 'b' ], [ 'b', 'c', 'c' ], [ 'c', 'a', 'a' ], [ 'c', 'a', 'b' ], [ 'c', 'a', 'c' ], [ 'c', 'b', 'a' ], [ 'c', 'b', 'b' ], [ 'c', 'b', 'c' ],
[ 'c', 'c', 'a' ], [ 'c', 'c', 'b' ], [ 'c', 'c', 'c' ], [ 'a', 'a', 'a', 'a' ], [ 'a', 'a', 'a', 'b' ], [ 'a', 'a', 'a', 'c' ], [ 'a', 'a', 'b', 'a' ],
[ 'a', 'a', 'b', 'b' ], [ 'a', 'a', 'b', 'c' ], [ 'a', 'a', 'c', 'a' ], [ 'a', 'a', 'c', 'b' ], [ 'a', 'a', 'c', 'c' ], [ 'a', 'b', 'a', 'a' ], [ 'a', 'b', 'a', 'b' ],
[ 'a', 'b', 'a', 'c' ], [ 'a', 'b', 'b', 'a' ], [ 'a', 'b', 'b', 'b' ], [ 'a', 'b', 'b', 'c' ], [ 'a', 'b', 'c', 'a' ], [ 'a', 'b', 'c', 'b' ], [ 'a', 'b', 'c', 'c' ],
[ 'a', 'c', 'a', 'a' ], [ 'a', 'c', 'a', 'b' ], [ 'a', 'c', 'a', 'c' ], [ 'a', 'c', 'b', 'a' ], [ 'a', 'c', 'b', 'b' ], [ 'a', 'c', 'b', 'c' ], [ 'a', 'c', 'c', 'a' ],
]
var nums = [ 'a', 'b', 'c' ]
var perms = []
var gen = G.baseNAll(nums)
for (var i = 0; i < 64; i++) {
perms.push(gen.next().value.slice())
}
expect(perms).to.eql(members)
})
})
describe('Clone submodule', () => {
it('clones combinations', () => {
var answers = []
for (var comb of G.combination([1, 2, 3], 2)) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.combination([1, 2, 3], 2)])
})
it('clones permutations', () => {
var answers = []
for (var comb of G.permutation([1, 2, 3], 2)) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.permutation([1, 2, 3], 2)])
answers = []
for (var comb of G.permutation([1, 2, 3])) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.permutation([1, 2, 3])])
})
it('clones power sets', () => {
var answers = []
for (var comb of G.powerSet([1, 2, 3])) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.powerSet([1, 2, 3])])
})
it('clones permutations of combinations', () => {
var answers = []
for (var comb of G.permutationCombination([1, 2, 3])) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.permutationCombination([1, 2, 3])])
})
it('clones base N', () => {
var answers = []
for (var comb of G.baseN([1, 2, 3])) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.baseN([1, 2, 3])])
})
it('clones cartesian products', () => {
var answers = []
for (var comb of G.cartesian([1, 2, 3], [5, 6], [1, 8])) {
answers.push(comb.slice())
}
expect(answers).to.eql([...G.clone.cartesian([1, 2, 3], [5, 6], [1, 8])])
})
})

27
js/package-lock.json

@ -0,0 +1,27 @@
{
"name": "js",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"generatorics": "^1.1.0"
}
},
"node_modules/generatorics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/generatorics/-/generatorics-1.1.0.tgz",
"integrity": "sha1-aVBgu42IuQmzAXGlyz1CR2hmETg=",
"engines": {
"node": ">=6.0.0"
}
}
},
"dependencies": {
"generatorics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/generatorics/-/generatorics-1.1.0.tgz",
"integrity": "sha1-aVBgu42IuQmzAXGlyz1CR2hmETg="
}
}
}

5
js/package.json

@ -0,0 +1,5 @@
{
"dependencies": {
"generatorics": "^1.1.0"
}
}
Loading…
Cancel
Save