Input: words = ["LEET","CODE"], result = "POINT"
Output: false
Explanation: There is no possible mapping to satisfy the equation, so we return false.
Note that two different characters cannot map to the same digit.
Constraints:
2 <= words.length <= 5
1 <= words[i].length, result.length <= 7
words[i], result contain only uppercase English letters.
The number of different characters used in the expression is at most 10.
Solutions
Solution 1
Thinking
Letters must map to distinct digits so the cryptarithm holds, with no leading zeros. At most \(10\) distinct letters means \(10!\) assignments if we permute first and only then evaluate the whole equation.
Processing columns from low to high prunes with the carry: after adding the addend digits, subtracting the result digit, and applying the old carry, the units digit must be \(0\) before we move on. A known mapping is reused; a free letter tries unused digits, forbidding a leading zero on a multi-digit word. When every column is done the leftover carry must be \(0\).
classSolution:defisAnyMapping(self,words,row,col,bal,letToDig,digToLet,totalRows,totalCols):# If traversed all columns.ifcol==totalCols:returnbal==0# At the end of a particular column.ifrow==totalRows:returnbal%10==0andself.isAnyMapping(words,0,col+1,bal//10,letToDig,digToLet,totalRows,totalCols)w=words[row]# If the current string 'w' has no character in the ('col')th index.ifcol>=len(w):returnself.isAnyMapping(words,row+1,col,bal,letToDig,digToLet,totalRows,totalCols)# Take the current character in the variable letter.letter=w[len(w)-1-col]# Create a variable 'sign' to check whether we have to add it or subtract it.ifrow<totalRows-1:sign=1else:sign=-1# If we have a prior valid mapping, then use that mapping.# The second condition is for the leading zeros.ifletterinletToDigand(letToDig[letter]!=0or(letToDig[letter]==0andlen(w)==1)orcol!=len(w)-1):returnself.isAnyMapping(words,row+1,col,bal+sign*letToDig[letter],letToDig,digToLet,totalRows,totalCols,)# Choose a new mapping.else:foriinrange(10):# If 'i'th mapping is valid then select it.ifdigToLet[i]=="-"and(i!=0or(i==0andlen(w)==1)orcol!=len(w)-1):digToLet[i]=letterletToDig[letter]=i# Call the function again with the new mapping.ifself.isAnyMapping(words,row+1,col,bal+sign*letToDig[letter],letToDig,digToLet,totalRows,totalCols,):returnTrue# Unselect the mapping.digToLet[i]="-"ifletterinletToDig:delletToDig[letter]# If nothing is correct then just return false.returnFalsedefisSolvable(self,words,result):# Add the string 'result' in the list 'words'.words.append(result)# Initialize 'totalRows' with the size of the list.totalRows=len(words)# Find the longest string in the list and set 'totalCols' with the size of that string.totalCols=max(len(word)forwordinwords)# Create a HashMap for the letter to digit mapping.letToDig={}# Create a list for the digit to letter mapping.digToLet=["-"]*10returnself.isAnyMapping(words,0,0,0,letToDig,digToLet,totalRows,totalCols)
classSolution{privatebooleanisAnyMapping(List<String>words,introw,intcol,intbal,HashMap<Character,Integer>letToDig,char[]digToLet,inttotalRows,inttotalCols){// If traversed all columns.if(col==totalCols){returnbal==0;}// At the end of a particular column.if(row==totalRows){return(bal%10==0&&isAnyMapping(words,0,col+1,bal/10,letToDig,digToLet,totalRows,totalCols));}Stringw=words.get(row);// If the current string 'w' has no character in the ('col')th index.if(col>=w.length()){returnisAnyMapping(words,row+1,col,bal,letToDig,digToLet,totalRows,totalCols);}// Take the current character in the variable letter.charletter=w.charAt(w.length()-1-col);// Create a variable 'sign' to check whether we have to add it or subtract it.intsign=(row<totalRows-1)?1:-1;// If we have a prior valid mapping, then use that mapping.// The second condition is for the leading zeros.if(letToDig.containsKey(letter)&&(letToDig.get(letter)!=0||(letToDig.get(letter)==0&&w.length()==1)||col!=w.length()-1)){returnisAnyMapping(words,row+1,col,bal+sign*letToDig.get(letter),letToDig,digToLet,totalRows,totalCols);}else{// Choose a new mapping.for(inti=0;i<10;i++){// If 'i'th mapping is valid then select it.if(digToLet[i]=='-'&&(i!=0||(i==0&&w.length()==1)||col!=w.length()-1)){digToLet[i]=letter;letToDig.put(letter,i);// Call the function again with the new mapping.if(isAnyMapping(words,row+1,col,bal+sign*letToDig.get(letter),letToDig,digToLet,totalRows,totalCols)){returntrue;}// Unselect the mapping.digToLet[i]='-';letToDig.remove(letter);}}}// If nothing is correct then just return false.returnfalse;}publicbooleanisSolvable(String[]wordsArr,Stringresult){// Add the string 'result' in the list 'words'.List<String>words=newArrayList<>();for(Stringword:wordsArr){words.add(word);}words.add(result);inttotalRows=words.size();// Find the longest string in the list and set 'totalCols' with the size of that string.inttotalCols=0;for(Stringword:words){if(totalCols<word.length()){totalCols=word.length();}}// Create a HashMap for the letter to digit mapping.HashMap<Character,Integer>letToDig=newHashMap<>();// Create a char array for the digit to letter mapping.char[]digToLet=newchar[10];for(inti=0;i<10;i++){digToLet[i]='-';}returnisAnyMapping(words,0,0,0,letToDig,digToLet,totalRows,totalCols);}}
classSolution{public:boolisAnyMapping(vector<string>&words,introw,intcol,intbal,unordered_map<char,int>&letToDig,vector<char>&digToLet,inttotalRows,inttotalCols){// If traversed all columns.if(col==totalCols){returnbal==0;}// At the end of a particular column.if(row==totalRows){return(bal%10==0&&isAnyMapping(words,0,col+1,bal/10,letToDig,digToLet,totalRows,totalCols));}stringw=words[row];// If the current string 'W' has no character in the ('COL')th index.if(col>=w.length()){returnisAnyMapping(words,row+1,col,bal,letToDig,digToLet,totalRows,totalCols);}// Take the current character in the variable letter.charletter=w[w.length()-1-col];// Create a variable 'SIGN' to check whether we have to add it or subtract it.intsign;if(row<totalRows-1){sign=1;}else{sign=-1;}/* If we have a prior valid mapping, then use that mapping. The second condition is for the leading zeros. */if(letToDig.count(letter)&&(letToDig[letter]!=0||(letToDig[letter]==0&&w.length()==1)||col!=w.length()-1)){returnisAnyMapping(words,row+1,col,bal+sign*letToDig[letter],letToDig,digToLet,totalRows,totalCols);}// Choose a new mapping.else{for(inti=0;i<10;i++){// If 'i'th mapping is valid then select it.if(digToLet[i]=='-'&&(i!=0||(i==0&&w.length()==1)||col!=w.length()-1)){digToLet[i]=letter;letToDig[letter]=i;// Call the function again with the new mapping.boolx=isAnyMapping(words,row+1,col,bal+sign*letToDig[letter],letToDig,digToLet,totalRows,totalCols);if(x==true){returntrue;}// Unselect the mapping.digToLet[i]='-';if(letToDig.find(letter)!=letToDig.end()){letToDig.erase(letter);}}}}// If nothing is correct then just return false.returnfalse;}boolisSolvable(vector<string>&words,stringresult){// Add the string 'RESULT' in the vector 'WORDS'.words.push_back(result);inttotalRows;inttotalCols;// Initialize 'TOTALROWS' with the size of the vector.totalRows=words.size();// Find the longest string in the vector and set 'TOTALCOLS' with the size of that string.totalCols=0;for(inti=0;i<words.size();i++){// If the current string is the longest then update 'TOTALCOLS' with its length.if(totalCols<words[i].size()){totalCols=words[i].size();}}// Create a HashMap for the letter to digit mapping.unordered_map<char,int>letToDig;// Create a vector for the digit to letter mapping.vector<char>digToLet(10,'-');returnisAnyMapping(words,0,0,0,letToDig,digToLet,totalRows,totalCols);}};