The code generates all possible permutations of an input array and combines them with operator combinations to create mathematical equations in both standard and nested formats. It uses functions such as spliceClone
, permute
, solve
, and reduce
to generate and evaluate these equations, storing the results in variables like permutations
, operators
, and equations
.
// permutation
function spliceClone(arr, i) {
return (a => a.splice(i, 1).concat(a))
// call it with a clone to preserve array reference
([].concat(arr))
}
function permute(array) {
return array.reduce((acc, cv, ci, arr) => {
const spliced = spliceClone(arr, ci);
// recursive
const perm = permute(spliced.slice(1))
.map(p => spliced.slice(0, 1).concat(p));
return acc.concat(perm);
}, [].concat(array));
}
var permutations = permute([1,3,4,6])
.filter(c => c.length === 4);
var op = ['+','-','*','/','^'];
var operators = op.reduce((acc, o) => acc.concat(op.reduce((acc2, o2) => acc2.concat(op.map(o3 => [o2, o3])), []).map(c => [o].concat(c))), [])
.filter(c => c.length === 3);
//console.log(operators);
function solve(op, p) {
switch(op) {
case '+':
return p[0] + p[1];
case '-':
return p[0] - p[1];
case '*':
return p[0] * p[1];
case '/':
return p[0] / p[1];
case '^':
return p[0] ^ p[1];
case '%':
return p[0] % p[1];
}
}
var equations = operators.reduce((acc, o) => {
return acc.concat(permutations.reduce((acc, p) => {
acc.push([
'(', p[0], o[0], p[1], ')', o[1], '(', p[2], o[2], p[3], ')',
'=',
solve(o[1], [
solve(o[0], p),
solve(o[2], p.slice(2))
])
]);
acc.push([
p[0], o[0], '(', p[1], o[1], '(', p[2], o[2], p[3], ')', ')',
'=',
solve(o[0], [
p[0],
solve(o[1], [
p[1],
solve(o[2], p.slice(2))
])
])
]);
acc.push([
'(', '(', p[0], o[0], p[1], ')', o[1], p[2], ')', o[2], p[3],
'=',
solve(o[2], [solve(o[1], [
solve(o[0], p),
p[2]
]),
p[3]
])
]);
return acc;
}, []));
}, [])
for(var e of equations) { // .filter(e => e[12] === 24)) {
console.log(e.join(' '))
}
/**
* Generates all permutations of the given array.
*
* @param {Array} array The input array.
* @returns {Array} An array of all permutations of the input array.
*/
function* permute(array) {
if (array.length === 1) {
yield array;
} else {
for (let i = 0; i < array.length; i++) {
const rest = array.slice(0, i).concat(array.slice(i + 1));
for (const perm of permute(rest)) {
yield [array[i]].concat(perm);
}
}
}
}
/**
* Creates a new array by removing the element at the given index and concatenating the rest of the array.
*
* @param {Array} array The input array.
* @param {Number} i The index of the element to remove.
* @returns {Array} A new array with the element at the given index removed.
*/
function spliceClone(array, i) {
return [...array.slice(0, i),...array.slice(i + 1)];
}
/**
* Creates a deep clone of the given array.
*
* @param {Array} array The input array.
* @returns {Array} A deep clone of the input array.
*/
function cloneArray(array) {
return [...array];
}
/**
* Represents an arithmetic operator.
*/
class Operator {
constructor(op, precedence) {
this.op = op;
this.precedence = precedence;
}
}
/**
* Represents a binary expression.
*/
class BinaryExpression {
constructor(left, op, right) {
this.left = left;
this.op = op;
this.right = right;
}
}
/**
* Represents an equation.
*/
class Equation {
constructor(left, op, right, equals) {
this.left = left;
this.op = op;
this.right = right;
this.equals = equals;
}
}
/**
* Generates all possible equations by combining permutations of a given array with a set of operators.
*
* @param {Array} array The array to permute.
* @param {Array} operators The set of operators to use.
* @returns {Array} An array of all possible equations.
*/
function generateEquations(array, operators) {
for (const perm of permute(array)) {
for (const op1 of operators) {
for (const op2 of operators) {
for (let i = 0; i < perm.length - 1; i++) {
const left = perm.slice(0, i + 1);
const right = perm.slice(i + 1);
const equation = new Equation(
new BinaryExpression(
new BinaryExpression(
new BinaryExpression(perm[0], op1.op, perm[1]),
op1.op,
new BinaryExpression(perm[2], op2.op, perm[3])
),
op1.op,
new BinaryExpression(perm[4], op2.op, perm[5])
),
'=',
solve([op1.op, op2.op], perm)
);
yield equation;
}
}
}
}
}
/**
* Evaluates a binary expression.
*
* @param {Array} op The operators used in the expression.
* @param {Array} values The values used in the expression.
* @returns {Number} The result of the expression.
*/
function solve(op, values) {
if (op.length === 1) {
return values[0];
} else {
const left = values.slice(0, 2);
const right = values.slice(2);
switch (op[0]) {
case '+':
return left[0] + left[1];
case '-':
return left[0] - left[1];
case '*':
return left[0] * left[1];
case '/':
return left[0] / left[1];
case '^':
return left[0] ^ left[1];
case '%':
return left[0] % left[1];
}
}
}
// Define the operators and their precedence
const operators = [
new Operator('^', 2),
new Operator('*', 2),
new Operator('/', 2),
new Operator('%', 2),
new Operator('+', 1),
new Operator('-', 1)
];
// Generate all possible equations
const equations = Array.from(generateEquations([1, 3, 4, 6], operators));
// Print the equations
for (const equation of equations) {
const left = equation.left;
const right = equation.right;
const equals = equation.equals;
const op1 = equation.op;
const op2 = op1.left.op;
const op3 = op1.right.op;
console.log(`(${left} ${op2} ${right.left}) ${op1.op} (${right.right}) ${op3} (${equals})`);
}
Code Breakdown
spliceClone(arr, i)
arr
by splicing a single element at index i
and concatenating the rest of the array.permute(array)
permutations
[1, 3, 4, 6]
.solve(op, p)
op
and operands p
.+
, -
, *
, /
, %
, ^
).operators
reduce
and concat
Used in operators
Generationop
array and combining operators in all possible ways.concat
to flatten the nested arrays.equations
reduce
Used in equations
Generationpermutations
array and combining permutations with operator combinations.concat
to flatten the nested arrays.a op1 b op2 c op3 d = result
op1(a, op2(b, c, d)) = result
solve
function.