#include <stdio.h> #include <stdlib.h> #include <stdbool.h>
#define SIZE 8 #define DIGITS 10
#define D 0 #define E 1 #define Y 2 #define N 3 #define R 4 #define O 5 #define S 6 #define M 7 #define CONTINUE 2 #define GOOD 0 #define BAD 1 /* SEND + MORE -------- MONEY -------- */
int singleVerify2(int code[SIZE], int *CARRY){ if(code[D] == -1) return CONTINUE; if(code[E] == -1) return CONTINUE; if(code[Y] == -1) return CONTINUE; int singleSum = code[D] + code[E]; if(singleSum > DIGITS) *CARRY = 1; else *CARRY = 0; if(singleSum % DIGITS == code[Y]) return GOOD; else return BAD; } /* SEND + MORE -------- MONEY -------- */ int tenVerify2(int code[SIZE], int *CARRY){ if(code[N] == -1) return CONTINUE; if(code[R] == -1) return CONTINUE; if(code[E] == -1) return CONTINUE; int tenSum = code[N] + code[R] + *CARRY; if(tenSum > DIGITS) *CARRY = 1; else *CARRY = 0; if(tenSum % DIGITS == code[E]) return GOOD; else return BAD; }
/* SEND + MORE -------- MONEY -------- */ int hundredVerify2(int code[SIZE], int *CARRY){ if(code[E] == -1) return CONTINUE; if(code[O] == -1) return CONTINUE; if(code[N] == -1) return CONTINUE; int hundredSum = code[E] + code[O] + *CARRY; if(hundredSum > DIGITS) *CARRY = 1; else *CARRY = 0; if(hundredSum % DIGITS == code[N]) return GOOD; else return BAD; } /* SEND + MORE -------- MONEY -------- */ int thousandVerify2(int code[SIZE], int *CARRY){ if(code[S] == -1) return CONTINUE; if(code[M] == -1) return CONTINUE; if(code[O] == -1) return CONTINUE; if(code[M] == -1) return CONTINUE; int thousandSum = code[S] + code[M] + *CARRY; if(thousandSum == code[M] * DIGITS + code[O]) return GOOD; else return BAD; } bool exhaustive2(int code[SIZE],int codeIndex, int digits[DIGITS]){ for(int i = 0 ; i < DIGITS; i++){ if(digits[i] == -1) continue; int middle = digits[i]; code[codeIndex] = middle; digits[i] = -1; int CARRY_ ,*CARRY; CARRY_ = 0; CARRY = &CARRY_; //first single position Verify int state = singleVerify2(code, CARRY); if(state == CONTINUE){ if(exhaustive2(code, codeIndex + 1, digits)) return true; else{ code[codeIndex] = -1; digits[i] = middle; continue; } }else if(state == BAD){ code[codeIndex] = -1; digits[i] = middle; continue; } //second ten position Verify state = tenVerify2(code, CARRY); if(state == CONTINUE){ if(exhaustive2(code, codeIndex + 1, digits)) return true; else{ code[codeIndex] = -1; digits[i] = middle; continue; } }else if(state == BAD){ code[codeIndex] = -1; digits[i] = middle; continue; } //third hundred position Verify state = hundredVerify2(code, CARRY); if(state == CONTINUE){ if(exhaustive2(code, codeIndex + 1, digits)) return true; else{ code[codeIndex] = -1; digits[i] = middle; continue; } }else if(state == BAD){ code[codeIndex] = -1; digits[i] = middle; continue; } //fourth thousand position Verify state = thousandVerify2(code, CARRY); if(state == CONTINUE){ if(exhaustive2(code, codeIndex + 1, digits)) return true; else{ code[codeIndex] = -1; digits[i] = middle; continue; } }else if(state == BAD){ code[codeIndex] = -1; digits[i] = middle; continue; } return true; } return false; }
void printCryptarithmetic2(char *str, int code[SIZE]){ for(int i = 0; i < SIZE; i++){ printf("%5c %5d\n",*str++, code[i]); } }
int main(){ //char *str = {'0D', '1E', '2Y', '3N', '4R', '5O', '6S', '7M'}; char str[] = {'D', 'E', 'Y', 'N', 'R', 'O', 'S', 'M'}; int digits[DIGITS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int code[SIZE] = {-1, -1, -1, -1, -1, -1, -1, -1}; if(exhaustive2(code, 0, digits)) printCryptarithmetic2(str, code); return 0; }
优化后
#include <stdio.h> #include <stdlib.h> #include <stdbool.h>
#define SIZE 8 #define DECIMAL 10 #define POSITION_NUM 13
#define CONTINUE 1 #define RETRY 0 #define D 0 #define E 1 #define Y 2 #define N 3 #define R 4 #define O 5 #define S 6 #define M 7 /* SEND + MORE -------- MONEY -------- */ //char str[] = {'D', 'E', 'Y', 'N', 'R', 'O', 'S', 'M'}; int** initPositions(int code[SIZE]){ int *positions[POSITION_NUM]; positions[0] = &code[D]; positions[1] = &code[E]; positions[2] = &code[Y]; positions[3] = &code[N]; positions[4] = &code[R]; positions[5] = &code[E]; positions[6] = &code[E]; positions[7] = &code[O]; positions[8] = &code[N]; positions[9] = &code[S]; positions[10] = &code[M]; positions[11] = &code[O]; positions[12] = &code[M]; return positions; }
//打印解决方案 void printCryptarithmetic(int code[SIZE]){ char str[] = {'D', 'E', 'Y', 'N', 'R', 'O', 'S', 'M'}; for(int i = 0; i < SIZE; i++){ printf("%5c %5d\n", str[i], code[i]); } printf("==========================\n"); } //加法器 int adder(int code[SIZE]){ int carry = 0; int **positions = initPositions(code); for(int j = 0; j < POSITION_NUM; j++){ //第j位的code未赋值,继续 赋值 if(*positions[j] == -1) return CONTINUE; //如果是加数,继续赋值 int index = (j + 1) % 3; if(index > 0) continue; //求和 int sum = *positions[j - 2] + *positions[j - 1] + carry; if(sum >= DECIMAL) carry = 1; else carry = 0; if(sum % DECIMAL == *positions[j]) continue ; else return RETRY; } //加数的位数 + 被加数的位数 + 和的位数 //为偶数(没有进位) if(POSITION_NUM % 2 == 0){ printCryptarithmetic(code); return RETRY; } /* SEND + MORE -------- MONEY -------- */ //为奇数,最高位的值与进位相等 if(code[SIZE - 1] == carry) printCryptarithmetic(code); return RETRY; } // void exhaustively(int code[SIZE], int codeIndex, int digits[DECIMAL]){ for(int i = 0 ; i < DECIMAL; i++){ if(digits[i] == -1) continue; int middle = digits[i]; code[codeIndex] = middle; digits[i] = -1; if(adder(code)) exhaustively(code, codeIndex + 1, digits); code[codeIndex] = -1; digits[i] = middle; } }
int main12(){ int digits[DECIMAL] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int code[SIZE] = {-1, -1, -1, -1, -1, -1, -1, -1}; exhaustively(code, 0, digits); return 0; }