-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy path1307-verbal-arithmetic-puzzle.js
72 lines (61 loc) · 2.37 KB
/
1307-verbal-arithmetic-puzzle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* 1307. Verbal Arithmetic Puzzle
* https://leetcode.com/problems/verbal-arithmetic-puzzle/
* Difficulty: Hard
*
* Given an equation, represented by words on the left side and the result on the right side.
*
* You need to check if the equation is solvable under the following rules:
* - Each character is decoded as one digit (0 - 9).
* - No two characters can map to the same digit.
* - Each words[i] and result are decoded as one number without leading zeros.
* - Sum of numbers on the left side (words) will equal to the number on the right side (result).
*
* Return true if the equation is solvable, otherwise return false.
*/
/**
* @param {string[]} words
* @param {string} result
* @return {boolean}
*/
var isSolvable = function(words, result) {
const charToDigit = new Map();
const usedDigits = new Set();
const leadingChars = new Set();
if (words.some(word => word.length > result.length)) return false;
words.forEach(word => {
if (word.length > 1) leadingChars.add(word[0]);
});
if (result.length > 1) leadingChars.add(result[0]);
return solve(0, 0, 0);
function solve(pos, wordIdx, carry) {
if (pos >= result.length) return carry === 0;
if (wordIdx <= words.length - 1) {
const word = words[wordIdx];
if (pos >= word.length) return solve(pos, wordIdx + 1, carry);
const char = word[word.length - 1 - pos];
if (charToDigit.has(char)) return solve(pos, wordIdx + 1, carry + charToDigit.get(char));
for (let digit = leadingChars.has(char) ? 1 : 0; digit <= 9; digit++) {
if (usedDigits.has(digit)) continue;
usedDigits.add(digit);
charToDigit.set(char, digit);
if (solve(pos, wordIdx + 1, carry + digit)) return true;
usedDigits.delete(digit);
charToDigit.delete(char);
}
return false;
}
const sumDigit = carry % 10;
const resultChar = result[result.length - 1 - pos];
if (!charToDigit.has(resultChar)) {
if (usedDigits.has(sumDigit) || (pos === result.length - 1 && sumDigit === 0)) return false;
charToDigit.set(resultChar, sumDigit);
usedDigits.add(sumDigit);
const success = solve(pos + 1, 0, (carry - sumDigit) / 10);
charToDigit.delete(resultChar);
usedDigits.delete(sumDigit);
return success;
}
return charToDigit.get(resultChar) === sumDigit && solve(pos + 1, 0, (carry - sumDigit) / 10);
}
};