Last active
September 17, 2018 18:23
-
-
Save cezary/23de2df2310540daf71bc545a3e11fa0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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