You don't need a map, just create an array that can hold all characters:
int letterToDigit[256];
For maximum portability you should use numeric_limits for the size:
1 2
|
#include <limits>
int letterToDigit[std::numeric_limits<char>::max()+1];
| |
When necessary, assign digits to the letters. Here's a simple example:
1 2 3 4
|
int digit=0;
for (int ch : "SENDMORY") {
letterToDigit[ch] = digit++;
}
| |
Now getting to the meat of the problem.
To go through all permutations of digits, you can star with a string of the digits and permute them:
1 2 3 4
|
string digits = "0123456789";
do {
...
} while (std::next_permutation(digits.begin(), digits.end()));
| |
With each permutation you could assign digits to the letterToDigit array:
1 2 3 4 5 6 7
|
void setLettersToDigits(const string &lettersInPuzzle, const string &digits)
{
size_t i=0;
for (size_t ch : lettersInPuzzle) {
letterToDigit[ch] = digits[i++] - '0';
}
}
| |
You also need a function that will take a word and convert it to a number:
1 2 3 4 5 6 7 8
|
int wordToNum(const string &str)
{
int result = 0;
for (size_t ch : str) {
result = result * 10 + letterToDigit[ch];
}
return result;
}
| |
With these pieces, putting together a full solution is fairly easy:
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
|
#include <iostream>
#include <limits>
#include <algorithm>
#include <string>
using std::numeric_limits;
using std::string;
using std::cout;
int letterToDigit[std::numeric_limits<char>::max()+1];
void setLettersToDigits(const string &lettersInPuzzle, const string &digits)
{
size_t i=0;
for (size_t ch : lettersInPuzzle) {
letterToDigit[ch] = digits[i++] - '0';
}
}
int wordToNum(const string &str)
{
int result = 0;
for (size_t ch : str) {
result = result * 10 + letterToDigit[ch];
}
return result;
}
bool checkSum(const string &addend1, const string &addend2, const string &sum)
{
int a1 = wordToNum(addend1);
int a2 = wordToNum(addend2);
int s = wordToNum(sum);
// cout << a1 << " + " << a2 << " = " << s << "?\n";
return a1 + a2 == s;
}
int
main()
{
string lettersInPuzzle = "SENDMORY";
string addend1 = "SEND";
string addend2 = "MORE";
string sum = "MONEY";
string digits = "0123456789";
bool found = false;
do {
setLettersToDigits(lettersInPuzzle, digits);
if (checkSum(addend1, addend2, sum)) {
cout << wordToNum(addend1) << " + "
<< wordToNum(addend2) << " = "
<< wordToNum(sum) << '\n';
found = true;
}
} while (std::next_permutation(digits.begin(), digits.end()));
if (!found) {
cout << "No solution found\n";
}
return !found; // return 0 for success, 1 for failure
}
| |
2817 + 368 = 3185
2817 + 368 = 3185
2819 + 368 = 3187
2819 + 368 = 3187
3712 + 467 = 4179
3712 + 467 = 4179
3719 + 457 = 4176
3719 + 457 = 4176
3821 + 468 = 4289
3821 + 468 = 4289
3829 + 458 = 4287
3829 + 458 = 4287
5731 + 647 = 6378
5731 + 647 = 6378
5732 + 647 = 6379
5732 + 647 = 6379
5849 + 638 = 6487
5849 + 638 = 6487
6415 + 734 = 7149
6415 + 734 = 7149
6419 + 724 = 7143
6419 + 724 = 7143
6524 + 735 = 7259
6524 + 735 = 7259
6851 + 738 = 7589
6851 + 738 = 7589
6853 + 728 = 7581
6853 + 728 = 7581
7316 + 823 = 8139
7316 + 823 = 8139
7429 + 814 = 8243
7429 + 814 = 8243
7531 + 825 = 8356
7531 + 825 = 8356
7534 + 825 = 8359
7534 + 825 = 8359
7539 + 815 = 8354
7539 + 815 = 8354
7643 + 826 = 8469
7643 + 826 = 8469
7649 + 816 = 8465
7649 + 816 = 8465
8324 + 913 = 9237
8324 + 913 = 9237
8432 + 914 = 9346
8432 + 914 = 9346
8542 + 915 = 9457
8542 + 915 = 9457
9567 + 1085 = 10652
9567 + 1085 = 10652 |
Notice that this prints out each solution twice. Can you figure out why? Also it takes my computer 1.6 seconds to get the solutions, but a human can find at least 1 solution in under an hour. Can you think of ways to speed this up?