@jrc03c/js-math-tools
Version:
some math tools for JS
196 lines (169 loc) • 4.33 kB
JavaScript
import { DataFrame, Series } from "./dataframe/index.mjs"
import { expect, test } from "@jrc03c/fake-jest"
import { factorial } from "./factorial.mjs"
import { forEach } from "./for-each.mjs"
import { isArray } from "./is-array.mjs"
import { isEqual } from "./is-equal.mjs"
import { map } from "./map.mjs"
import { permutations, permutationsIterator } from "./permutations.mjs"
import { range } from "./range.mjs"
import { set } from "./set.mjs"
import { sort } from "./sort.mjs"
function depthSort(a, b) {
let i = 0
while (i < a.length && i < b.length && a[i] === b[i]) {
i++
}
return a[i] < b[i] ? -1 : 1
}
function turnIntoStrings(arr) {
return map(arr, item => JSON.stringify(item))
}
function getNumberOfPermutations(arr, r) {
const n = arr.length
return factorial(n) / factorial(n - r)
}
test("tests that permutations can be correctly computed", () => {
const a = [2, 3, 4]
const bTrue = sort(
set(
turnIntoStrings([
[],
[],
[],
[],
[],
[],
]),
),
)
const bPred = sort(set(turnIntoStrings(permutations(a))))
expect(bPred).toStrictEqual(bTrue)
const c = ["a", "b", "c", "d"]
const dTrue = sort(
set(
turnIntoStrings([
["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"],
]),
),
)
const dPred = sort(set(turnIntoStrings(permutations(c))))
expect(dPred).toStrictEqual(dTrue)
for (let i = 2; i < 10; i++) {
const e = range(0, i).toArray()
expect(permutations(e).length).toBe(factorial(i))
}
for (let i = 1; i < 8; i++) {
const e = range(0, 8).toArray()
expect(permutations(e, i).length).toBe(getNumberOfPermutations(e, i))
}
const f = [2, [3, 4, [5]]]
const gPred = sort(permutations(f, 3), depthSort)
const gTrue = sort(
[
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
[],
],
depthSort,
)
expect(isEqual(gPred, gTrue)).toBe(true)
const h = new Series({ hello: [1, 2, 3, 4, 5] })
expect(isEqual(permutations(h, 2), permutations(h.values, 2))).toBe(true)
const i = new DataFrame({ foo: [1, 2, 3, 4, 5], bar: [6, 7, 8, 9, 10] })
expect(isEqual(permutations(i, 2), permutations(i.values, 2))).toBe(true)
const jTrue = sort(
[
[],
[],
[],
[],
[],
[],
],
depthSort,
)
const jPred = sort(permutations([2n, 3n, 4n]), depthSort)
expect(jPred).toStrictEqual(jTrue)
const k = range(0, 10).toArray()
const m = []
for (const perm of permutationsIterator(k, 3)) {
m.push(perm.slice())
}
expect(m.length).toBe(getNumberOfPermutations(k, 3))
expect(
typeof permutationsIterator(k, 3) === "object" &&
!isArray(permutationsIterator(k, 3)),
).toBe(true)
})
test("tests that errors are thrown when trying to get permutations from non-arrays", () => {
const wrongs = [
0,
1,
2.3,
-2.3,
Infinity,
-Infinity,
NaN,
"foo",
true,
false,
null,
undefined,
Symbol.for("Hello, world!"),
x => x,
function (x) {
return x
},
{ hello: "world" },
]
forEach(wrongs, a => {
forEach(wrongs, b => {
expect(() => permutations(a, b)).toThrow()
})
})
})