r/dailyprogrammer - 2018-01-08
https://www.reddit.com/r/dailyprogrammer/comments/7p5p2o/20180108_challenge_346_easy_cryptarithmetic_solver/
HTML
Warning: you may get unresponsive script warning
CSS
pre {
background-color: #DDD;
padding: 0.5em 1em;
}
Babel + JSX
console.clear();
function log(msg, ...rest){
const pre = document.createElement('pre');
document.body.appendChild(pre);
pre.innerText = JSON.stringify(msg, null, 2);
if (rest.length) log(...rest);
}
function newArray(n){
return (new Array(n)).fill().map((_,i) => i);
}
function factorial(n){
return newArray(n).map(i => i+1).reduce((prod, mul) => prod * mul, 1);
}
function permutations(n,r){
return factorial(n) / factorial(n - r);
};
function substitute(letters, map){
return letters
.map(letter => map[letter])
.reverse()
.reduce(
(sum, num, index) => sum + num * Math.pow(10, index),
0
);
}
function solve(equation){
const [ left, right ] = equation.split(/==?/);
const add = left.split('+').map(a => a.trim().split(''));
const sum = right.trim().split('');
const letters = [...add,sum].reduce((acc, a) => acc.concat(a), [])
.filter((letter, index, letters) => letters.indexOf(letter) === index);
return newArray(permutations(10, letters.length))
.map(variant => {
const numberPool = newArray(10);
return letters.reduce((acc, letter, index) => {
return {
...acc,
[letter]: numberPool.splice(
Math.floor(variant / permutations(10,index)) % numberPool.length,
1)[0]
};
}, {});
})
.filter(letterCombination => {
return [ ...add.map(a => a[0]), sum[0] ]
.every(l => letterCombination[l] !== 0);
})
.filter((letterCombination, index) => {
const total = add
.map(left => substitute(left, letterCombination))
.reduce((sum, addr) => sum + addr, 0);
const right = substitute(sum, letterCombination);
return total === right;
});
}
function run(equation){
log(equation)
const start = performance.now();
const substitutions = solve(equation);
const end = performance.now();
substitutions.map(sub => {
log(equation.split('').map(l => sub.hasOwnProperty(l) ? sub[l] : l).join(''));
...