algorithm
cryptarithms/alphametics 字母算术
https://www.zhihu.com/question/64650060/answer/223222162
https://www.woodpecker.org.cn/diveintopython3/advanced-iterators.html
https://stackoverflow.com/questions/9960908/permutations-in-javascript
function letter2number(_puzzle){
//1.将字母等式parse成checkfunc
const firstLetters = [];
const digitals = new Array(10).fill(undefined).map((none, i) => i);
let letters = [];
let puzzle = _puzzle;
puzzle.toUpperCase().match(/([A-Z]+)/g)
.forEach(word => puzzle = puzzle.replace(word,
new Array(word.length).fill(undefined)
.map((none, i) => (
i === 0 && firstLetters.push(word[i]),
letters.push(word[i]),
`${Math.pow(10, word.length - i - 1)} * ${word[i]}`
))
.join(' + ')
));
letters = [...new Set(letters)];
if(letters.length > 10) throw new Error('超过10个字母');
let checkfunc = new Function(letters.join(','),
`if(${[...new Set(firstLetters)].map(letter => `!${letter}`).join(' || ')}) return false;
return ${puzzle}`
);
//2.枚举全排列
let used = [];
let result = (function permute(input){
let result;
for (let i = 0; i < input.length; i++) {
let ch = input.splice(i, 1)[0];
used.push(ch);
if (input.length === 0) {
if(checkfunc(... result = used.slice())) return result;
}
if(result = permute(input)) return result;
input.splice(i, 0, ch);
used.pop();
}
})(digitals);
//3.输出
if(result) {
let digitalPuzzle = _puzzle;
let letter2digital = {};
letters.map((letter, i) =>{
let digital = result[i];
digitalPuzzle = digitalPuzzle.replace(new RegExp(letter, 'g'), digital);
letter2digital[letter] = digital;
})
return {puzzle: _puzzle, digitalPuzzle, letter2digital}
}
throw new Error('无解!');
}
console.time('cal');
console.log(letter2number('HAWAII + IDAHO + IOWA + OHIO == STATES'));
console.timeEnd('cal');