ab@unido.UUCP (12/05/85)
Here is a programm to solve cryptarithmetic puzzles like this one:
SEND
+ MORE
======
MONEY
where to substitute the letters with digits.
The program will give you all possible solutions and with the verbose option,
you can watch the searching process.
Enjoy!
--
Andreas Bormann
University of Dortmund [UniDo]
West Germany
Uucp: ab@unido.uucp
Path: {USA}!seismo!{mcvax}!unido!ab
{Europe}!{cernvax,diku,enea,ircam,mcvax,prlb2,tuvie,ukc}!unido!ab
Bitnet: ab@ddoinf6.bitnet
\
Missiles: -=>-->-*> N 51 29' 05" E 07 24' 42"
/
---CUT HERE------CUT HERE------CUT HERE------CUT HERE------CUT HERE------CUT HE
/*
* solve.c - A program to solve cryptarithmetic puzzles
*
* (C) Copyright 1985 by Andreas Bormann (ab@unido.uucp)
*
* Usage: solve [-v] <word1> <word2> <sum>
*/
int word1[50], word2[50], sum[51];
char letter[11];
int digit[11];
int vflag, l, n1, n2, n3, cnt, sct;
main(argc, argv)
int argc;
char *argv[];
{
register int i,j,k;
if(argc > 1 && strcmp("-v", argv[1]) == 0) {
vflag++;
argc--;
argv++;
}
if(argc < 4) {
printf("Usage: solve [-v] <word1> <word2> <sum>\n");
exit(1);
}
i = j = k = l = 0;
while(argv[1][i]) i++;
while(argv[2][j]) j++;
while(argv[3][k]) k++;
do {
word1[l] = i > 0 ? setletter(argv[1][--i]) : 10;
word2[l] = j > 0 ? setletter(argv[2][--j]) : 10;
sum[l] = k > 0 ? setletter(argv[3][--k]) : 10;
l++;
} while(i > 0 || j > 0 || k > 0);
sum[l] = word1[l] = word2[l] = 10;
for(k = 0; k < 10; k++)
digit[k] = -1;
n1 = setletter(argv[1][0]);
n2 = setletter(argv[2][0]);
n3 = setletter(argv[3][0]);
nextdigit(0);
printf("Search finished after %d tests and %d partial solutions.\n",
cnt, sct);
exit(0);
}
setletter(c)
register char c;
{
register int k;
for(k = 0; k < 10; k++) {
if(letter[k] == c)
return(k);
if(letter[k] == 0) {
letter[k] = c;
return(k);
}
}
printf("No more than 10 different letters allowed!\n");
exit(1);
}
nextdigit(d)
{
register i,k;
if(d == 10)
return;
sct++;
if(vflag) {
print(word1, l, ' ');
print(word2, l, '+');
for(i = 0; i <= l; i++)
putchar('=');
putchar('\n');
print(sum, l, ' ');
printf("\n");
}
for(k = 0; k < 10; k++) {
if(k == 0 && (d == n1 || d == n2 || d == n3))
goto nextk;
for(i = 0; i < d; i++)
if(digit[i] == k) goto nextk;
digit[d] = k;
if(addok())
nextdigit(d+1);
nextk:
;
}
digit[d] = -1;
}
addok()
{
register int k, w1, w2, s, s1, carry, i;
cnt++;
k = 0;
carry = 0;
while(word1[k] != 10 || word2[k] != 10 || sum[k] != 10) {
if((w1 = digit[word1[k]]) == -1)
return(1);
if((w2 = digit[word2[k]]) == -1)
return(1);
if((s = digit[sum[k]]) == -1)
return(1);
s1 = w1 + w2 + carry;
if(s1 > 9) {
s1 -= 10;
carry = 1;
} else
carry = 0;
if(s != s1)
return(0);
k++;
}
if(carry)
return(0);
printf("Solution found after %d tests and %d partial solutions:\n\n",
cnt, sct);
printf("%c = %d", letter[0], digit[0]);
for(i = 1; letter[i]; i++)
printf(", %c = %d", letter[i], digit[i]);
printf("\n\n");
print(word1, k, ' ');
print(word2, k, '+');
for(i = 0; i <= k; i++)
putchar('=');
putchar('\n');
print(sum, k, ' ');
printf("\n\n");
return(0);
}
print(z, k, s)
int z[], k;
char s;
{
char c;
putchar(s);
while(k-- > 0) {
if((c = digit[z[k]]) == -1)
c = letter[z[k]];
else
c += '0';
if(z[k] == 10)
c = ' ';
putchar(c);
}
putchar('\n');
}