2
public static boolean isSolvable(String[] words, String result) {3
// reverse all strings to facilitate add calculation.4
for (int i = 0; i < words.length; i++) {5
words[i] = new StringBuilder(words[i]).reverse().toString();7
result = new StringBuilder(result).reverse().toString();8
if (!checkLength(words, result)) {11
boolean[] visited = new boolean[10]; // digit 0, 1, ..., 912
int[] chToDigit = new int[26];13
Arrays.fill(chToDigit, -1);14
return dfs(0, 0, 0, visited, chToDigit, words, result);17
/** Elminate the case where result is too long word1: AAA word2: BBB result: XXXXXXXXX */18
private static boolean checkLength(String[] words, String result) {20
for (String word : words) {21
maxLen = Math.max(maxLen, word.length());23
return result.length() == maxLen || result.length() == maxLen + 1;27
Put all words like this:34
carrier, the one contributed from previous calculation35
chToDigit, 26 int array, which records choosen digit for 'A', 'B', 'C', ... If not choosen any, default is -137
private static boolean dfs(45
if (i == words.length) {46
char ch = result.charAt(j);47
// (i, i) at bottom right corner. final check48
if (j == result.length() - 1) {49
// 1. check if carrier is equal or greater than 10. If so, false.53
// 2. check if result.length() > 1 && result.lastCh is zero. If so the false.54
if (j > 0 && j == result.length() - 1 && chToDigit[ch - 'A'] == 0) {57
// not selected, can select any. True.58
if (chToDigit[ch - 'A'] == -1) {59
System.out.println(Arrays.toString(chToDigit));61
} else { // if selected, check if it matches with carrier. Also, carrier can't be 0. result63
return chToDigit[ch - 'A'] == carrier;65
} else { // reached normal result line.66
// 1. if not selected. Use current carrier's unit digit67
if (chToDigit[ch - 'A'] == -1) {68
int selectedDigit = carrier % 10;69
// For example carrier = 13. selectedDigit = 3. ch = 'H'. Should set 3 to 'H'.70
// But 3 is already taken by 'B' previously. So wrong.71
if (visited[selectedDigit]) {74
visited[selectedDigit] = true;75
chToDigit[ch - 'A'] = selectedDigit;76
if (dfs(0, j + 1, carrier / 10, visited, chToDigit, words, result)) {79
chToDigit[ch - 'A'] = -1;80
visited[selectedDigit] = false;81
} else { // 2. selected82
// just need to check if ch.digit equals to unit digit.83
if (chToDigit[ch - 'A'] != carrier % 10) {86
boolean ans = dfs(0, j + 1, carrier / 10, visited, chToDigit, words, result);90
} else { // normal word91
String word = words[i];92
// 1. check if j is equal or greater than word.len. If so pass to next word.93
if (j >= word.length()) {94
boolean ans = dfs(i + 1, j, carrier, visited, chToDigit, words, result);97
// 2. check if it's last ch, word.len is greater than 1, and is '0'. If so false;98
if (j == word.length() - 1 && word.length() > 1 && chToDigit[word.charAt(j) - 'A'] == 0) {101
char ch = word.charAt(j);102
// 3. check if word.ch is selected. Just add current digit and move to next word.103
if (chToDigit[ch - 'A'] != -1) {104
int newSum = carrier + chToDigit[ch - 'A'];105
boolean ans = dfs(i + 1, j, newSum, visited, chToDigit, words, result);108
for (int k = 0; k < visited.length; k++) {113
chToDigit[ch - 'A'] = k;114
int newSum = k + carrier;115
boolean ans = dfs(i + 1, j, newSum, visited, chToDigit, words, result);120
chToDigit[ch - 'A'] = -1;