Cryptarithmetic Puzzles

    技术2023-11-19  98

    #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; }

    Processed: 0.011, SQL: 9