/** Class aggregating permutation methods. */
class permutationLib{
/**
* Counts the number of permutations using n permutate r (nPr).
* @param {number} n - The n value in nPr
* @param {number} r - The r value in nPr
* @return {number} Numerical value representing the evaluation of nPr
*/
static countPermutation(n, r){
if(n === 0 || r === 0 || n < r){
return 1;
}
return permutationLib.factorial(n) / permutationLib.factorial(n - r);
}
/**
* Evaluates a factorial n.
* @param {number} n - Factorial to evaluate
* @return {number} Result of the factorial evaluation
*/
static factorial(n){
if(n === 0){
return 1;
}
let ret = 1;
for (let i = 1; i <= n; i++){
ret *= i;
}
return ret;
}
/**
* Finds all possible permutations of length k in a given array.
* @param {number[]} inArr - The input array to permutate
* @param {number} k - The length of output arrays
* @return {number[][]} Array of arrays representing all permutations of k length.
*/
static kPermutations(inArr, k){
let ret = [];
if (k > inArr.length){
return [inArr];
}
let newArr = new Array(k, 0);
const arrUnique = (arr) => {
let setTest = new Set(arr);
if (setTest.size === arr.length){
return true;
}
return false;
}
const permutate = (curArr, newArr, outSize, idx) => {
if (idx === outSize){
if (arrUnique(curArr)){
ret.push(curArr);
}
return;
}
let nextArr = [...curArr];
for (let i = 0; i < newArr.length; i++){
nextArr[idx] = newArr[i]
permutate(nextArr, newArr, outSize, idx+1)
nextArr = [...curArr];
}
}
permutate(new Array(k), inArr, k, 0);
return ret;
}
/**
* Finds all possible permutations of in a given array.
* @param {number[]} inArr - The input array to permutate
* @return {number[][]} Array of arrays representing all permutations.
*/
static permutation(inArr){
let ret = [];
const permute = (arr, size) => {
if (size === 1) {
ret.push([...arr]);
} else {
for (let i = 0; i < size; i++) {
permute(arr, size - 1);
if(size % 2 === 0){
let temp = arr[size-1];
arr[size-1] = arr[i];
arr[i] = temp;
} else {
let temp = arr[size-1];
arr[size-1] = arr[0];
arr[0] = temp;
}
}
}
}
permute(inArr, inArr.length);
return ret;
}
}
/** Class aggregating combinatorics methods. */
class combinationLib{
/**
* Evaluates statistical correlation of two arrays.
* @param {number[]} inArr - Input to find power sets for
* @return {array} Array of Sets representing all power sets.
*/
static powerSet(inArr){
let ret = [];
const psFunc = (items) =>{
let N = items.length;
for (let i = 0; i < Math.pow(2, N); i++){
let comb=[]
for (let j = 0; j < N; j++){
if ((i >> j) % 2 === 1){
comb.push(items[j]);
}
}
ret.push(new Set(comb));
}
}
psFunc(inArr);
return ret;
}
/**
* Evaluates the number of power sets with the given size
* @param {number} size - Input to find power sets for
* @return {number} Numerical value representing the evaluation for the number of power sets
*/
static countPowerSet(size){
return Math.pow(2, size);
}
/**
* Counts the number of permutations using n choose r (nCr).
* @param {number} n - The n value in nCr
* @param {number} r - The r value in nCr
* @return {number} Numerical value representing the evaluation of nCr
*/
static countCombinations(n, r){
if (n === r || n === 0 || r === 0) {
return 1;
}
return permutationLib.countPermutation(n, r) / permutationLib.factorial(r);
}
/**
* Finds all possible combinations of length k in a given array.
* @param {number[]} inArr - The input array to combine
* @param {number} k - The length of the possible combinations
* @return {array} Array of Sets representing all permutations of k length.
*/
static combinations(inArr, k){
let ret = [];
let N = inArr.length;
let pointers = Array.of(k);
let i = 0;
let r = 0;
if (k > N){
return [inArr];
}
while (r >= 0){
if (i <= (N + (r - k))){
pointers[r] = i;
if (r === k-1){
let newComb = []
for (let j = 0; j < pointers.length; j++){
newComb.push(inArr[pointers[j]]);
}
ret.push(new Set(newComb));
i++
}
else
{
i = pointers[r] + 1;
r++
}
}
else
{
r--;
if(r >= 0){
i = pointers[r]+1;
}
}
}
return ret;
}
}
module.exports = {
combinationLib: combinationLib,
permutationLib: permutationLib,
};