Skip to content

Instantly share code, notes, and snippets.

@cezary
Last active September 17, 2018 18:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cezary/23de2df2310540daf71bc545a3e11fa0 to your computer and use it in GitHub Desktop.
Save cezary/23de2df2310540daf71bc545a3e11fa0 to your computer and use it in GitHub Desktop.
// https://stackoverflow.com/a/20871714
const permutator = (inputArr) => {
let result = [];
const permute = (arr, m = []) => {
if (arr.length === 0) {
result.push(m)
} else {
for (let i = 0; i < arr.length; i++) {
let curr = arr.slice();
let next = curr.splice(i, 1);
permute(curr.slice(), m.concat(next))
}
}
}
permute(inputArr)
return result;
}
// https://stackoverflow.com/a/48063779
const postfixToInfix = RPN => {
let convert = RPN.replace(/\^/g,'**').split(/\s+/g).filter(el => !/\s+/.test(el) && el !== '')
let stack = []
let result = []
let precedence = {null : 4 ,'**':3 ,'/' : 2,'*': 2,'+':1,'-':1 }
convert.forEach(symbol => {
let stra,strb
if(!isNaN(parseFloat(symbol)) && isFinite(symbol)){
result.push(symbol)
stack.push(null)
}
else if (Object.keys(precedence).includes(symbol)) {
let [a,b,opa,opb] = [result.pop(),result.pop(),stack.pop(),stack.pop()]
if(precedence[opb] < precedence[symbol]) {
strb = `(${b})`
}
else{
strb = `${b}`
}
if((precedence[opa] < precedence[symbol]) || ((precedence[opa] === precedence[symbol]) && ["/","-"].includes(symbol) )){
stra = `(${a})`
}
else {
stra = `${a}`
}
result.push(strb +symbol + stra)
stack.push(symbol)
}
else throw `${symbol} is not a recognized symbol`
})
if(result.length === 1) return result.pop()
else throw `${RPN} is not a correct RPN`
}
const getOperations = () => {
const operators = ['+','-','*','/'];
let operations = [];
for (var i = 0; i < operators.length; i++) {
for (var j = 0; j < operators.length; j++) {
for (var k = 0; k < operators.length; k++) {
operations.push([operators[i], operators[j], operators[k]]);
}
}
}
return operations;
}
const operations = getOperations();
const operatorFnMap = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => a / b
}
const calculateRPN = (values) => {
values = values.split(' ');
const temp = [];
for (value of values) {
if (parseInt(value, 10) == value) {
temp.push(parseInt(value, 10));
} else {
const operator = value;
const val2 = temp.pop();
const val1 = temp.pop();
const newValue = operatorFnMap[operator](val1, val2);
temp.push(newValue);
}
}
return temp[0];
}
const solve24 = (...values) => {
const valuePermutations = permutator(values);
const combinations = [];
valuePermutations.forEach(([v1, v2, v3, v4]) => {
operations.forEach(([o1, o2, o3]) => {
combinations.push(`${v1} ${v2} ${o1} ${v3} ${o2} ${v4} ${o3}`);
combinations.push(`${v1} ${v2} ${v3} ${o1} ${o2} ${v4} ${o3}`);
combinations.push(`${v1} ${v2} ${v3} ${o1} ${v4} ${o2} ${o3}`);
combinations.push(`${v1} ${v2} ${v3} ${v4} ${o1} ${o2} ${o3}`);
})
})
const solutions = combinations.filter(combination => calculateRPN(combination) === 24)
return solutions.map(postfixToInfix);
}
console.log(solve24(2, 4, 5, 8));
console.log(solve24(2, 3, 5, 12));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment