A cryptarithm is a mathematical puzzle where the g...
बनाया गया: 23 जून 2025
बनाया गया: 23 जून 2025
A cryptarithm is a mathematical puzzle where the goal is to find the correspondence between letters and digits such that the given arithmetic equation consisting of letters holds true.
Given a cryptarithm as an array of strings crypt, count the number of its valid solutions.
The solution is valid if each letter represents a different digit, and the leading digit of any multi-digit number is not zero.
crypt has the following structure: [word1, word2, word3], which stands for the word1 + word2 = word3 cryptarithm.
Example
For crypt = ["SEND", "MORE", "MONEY"], the output should be solution(crypt) = 1, because there is only one solution to this cryptarithm: O = 0, M = 1, Y = 2, E = 5, N = 6, D = 7, R = 8, and S = 9 (9567 + 1085 = 10652).
For crypt = ["GREEN", "BLUE", "BLACK"], the output should be solution(crypt) = 12, because there are 12 possible valid solutions:
54889 + 6138 = 61027
18559 + 2075 = 20634
72449 + 8064 = 80513
48229 + 5372 = 53601
47119 + 5261 = 52380
36887 + 4028 = 40915
83447 + 9204 = 92651
74655 + 8326 = 82981
in c++ wihttu comments
Below is a compact, fully-commented C++17 program that counts all valid assignments for a “word + word = word” cryptarithm under the usual rules (distinct digits, no leading zero on multi-digit words).
cpp#include <bits/stdc++.h> using namespace std; /* Count the number of solutions of a cryptarithm word1 + word2 = word3 -------------------------------------------------------------------- • Each different uppercase letter must map to a different decimal digit 0-9. • A leading letter of any multi-digit word may NOT be 0. -------------------------------------------------------------------- Algorithm (classic column–wise back-tracking with pruning): 1. Collect the set of distinct letters (≤10 by the pigeon-hole rule). 2. Work column-by-column from least-significant (rightmost) to most-significant (leftmost). Carry is threaded through recursion. 3. When we meet a letter that is still unassigned, try every still-free digit that respects the “no leading zero” rule for that word. 4. Prune immediately when the current column sum (d1 + d2 + carry) cannot match the already-assigned digit of word3 (mod 10). 5. When we reach the end of the longest word, a carry of 0 means we found a complete valid assignment → increment the counter. Complexity: worst-case 10! (≈3.6 M) assignments, but the column pruning makes typical instances (even “SEND+MORE=MONEY”) very fast. */ struct CryptCounter { array<int, 26> letter2digit; // -1 if unassigned, else 0-9 int usedMask = 0; // bit i set ⇒ digit i already used vector<string> words; // reversed for easy indexing int maxLen; // length of longest word int solutionCount = 0; // convenience: return digit for letter idx (0-25) or -1 if unassigned inline int d(int idx) const { return letter2digit[idx]; } // Recursively solve column by column void dfs(int col, int row, int carry) { if (col == maxLen) { // past leftmost column if (carry == 0) ++solutionCount; return; } if (row < 3) { // process word[row] at this column const string &w = words[row]; int letter = (col < (int)w.size()) ? w[col] - 'A' : -1; if (letter == -1) { // this word has no letter here (implicit 0) dfs(col, row + 1, carry); return; } int digit = d(letter); bool leading = (col == (int)w.size() - 1 && w.size() > 1); // leftmost char if (row < 2) { // operands: choose / check digit freely if (digit != -1) { dfs(col, row + 1, carry + digit); } else { for (int x = 0; x <= 9; ++x) { if (usedMask & (1 << x)) continue; if (x == 0 && leading) continue; // no leading 0 letter2digit[letter] = x; usedMask |= 1 << x; dfs(col, row + 1, carry + x); usedMask &= ~(1 << x); letter2digit[letter] = -1; } } } else { // row == 2 → result word: must satisfy sum %10 int sum = carry % 10; if (digit != -1) { if (digit != sum) return; dfs(col + 1, 0, carry / 10); } else { if (usedMask & (1 << sum)) return; if (sum == 0 && leading) return; letter2digit[letter] = sum; usedMask |= 1 << sum; dfs(col + 1, 0, carry / 10); usedMask &= ~(1 << sum); letter2digit[letter] = -1; } } } } }; // API wrapper ----------------------------------------------------------- long long solution(const vector<string> &crypt) { CryptCounter cc; cc.letter2digit.fill(-1); cc.words.resize(3); // reverse words for column-wise indexing from right cc.maxLen = 0; for (int i = 0; i < 3; ++i) { cc.words[i] = string(crypt[i].rbegin(), crypt[i].rend()); cc.maxLen = max(cc.maxLen, (int)crypt[i].size()); } cc.dfs(0, 0, 0); return cc.solutionCount; } // ------------------------------- demo ---------------------------------- #ifdef RUN_DEMO int main() { vector<string> test1 = {"SEND", "MORE", "MONEY"}; cout << solution(test1) << '\n'; // prints 1 vector<string> test2 = {"GREEN", "BLUE", "BLACK"}; cout << solution(test2) << '\n'; // prints 12 } #endif
cryptarithm.cpp
),bashg++ -std=c++17 -O2 cryptarithm.cpp -o cryptarithm
RUN_DEMO
(e.g. -DRUN_DEMO
) if you’d like the two sample cases to run automatically:bashg++ -std=c++17 -O2 -DRUN_DEMO cryptarithm.cpp -o cryptarithm ./cryptarithm # should print: 1 then 12
Feel free to integrate the solution()
routine into any contest harness or testing framework you like—its only input is the vector<string>
describing the three words, and it returns the total number of distinct valid assignments.