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

  1. function letter2number(_puzzle){
  2. //1.将字母等式parse成checkfunc
  3. const firstLetters = [];
  4. const digitals = new Array(10).fill(undefined).map((none, i) => i);
  5. let letters = [];
  6. let puzzle = _puzzle;
  7. puzzle.toUpperCase().match(/([A-Z]+)/g)
  8. .forEach(word => puzzle = puzzle.replace(word,
  9. new Array(word.length).fill(undefined)
  10. .map((none, i) => (
  11. i === 0 && firstLetters.push(word[i]),
  12. letters.push(word[i]),
  13. `${Math.pow(10, word.length - i - 1)} * ${word[i]}`
  14. ))
  15. .join(' + ')
  16. ));
  17. letters = [...new Set(letters)];
  18. if(letters.length > 10) throw new Error('超过10个字母');
  19. let checkfunc = new Function(letters.join(','),
  20. `if(${[...new Set(firstLetters)].map(letter => `!${letter}`).join(' || ')}) return false;
  21. return ${puzzle}`
  22. );
  23. //2.枚举全排列
  24. let used = [];
  25. let result = (function permute(input){
  26. let result;
  27. for (let i = 0; i < input.length; i++) {
  28. let ch = input.splice(i, 1)[0];
  29. used.push(ch);
  30. if (input.length === 0) {
  31. if(checkfunc(... result = used.slice())) return result;
  32. }
  33. if(result = permute(input)) return result;
  34. input.splice(i, 0, ch);
  35. used.pop();
  36. }
  37. })(digitals);
  38. //3.输出
  39. if(result) {
  40. let digitalPuzzle = _puzzle;
  41. let letter2digital = {};
  42. letters.map((letter, i) =>{
  43. let digital = result[i];
  44. digitalPuzzle = digitalPuzzle.replace(new RegExp(letter, 'g'), digital);
  45. letter2digital[letter] = digital;
  46. })
  47. return {puzzle: _puzzle, digitalPuzzle, letter2digital}
  48. }
  49. throw new Error('无解!');
  50. }
  51. console.time('cal');
  52. console.log(letter2number('HAWAII + IDAHO + IOWA + OHIO == STATES'));
  53. console.timeEnd('cal');