Advertisement
Guest User

solve.c

a guest
Jan 10th, 2018
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.45 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define DELIM " \n\r"
  6.  
  7. enum op {OP_RET, OP_MAD, OP_LDI, OP_LDC, OP_SWP};
  8.  
  9. static const long pow10[] = {
  10.     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
  11. };
  12.  
  13. static int
  14. execute(const char *ops, const long *constants)
  15. {
  16.     long a = 0;
  17.     long b = 0;
  18.     long c = 0;
  19.     long x = 0;
  20.     long tmp;
  21.     for (;; ops++) {
  22.         switch ((enum op)*ops) {
  23.             case OP_RET:
  24.                 return a == x;
  25.             case OP_MAD:
  26.                 a += pow10[b] * c;
  27.                 b--;
  28.                 break;
  29.             case OP_LDI:
  30.                 b = *++ops;
  31.                 break;
  32.             case OP_LDC:
  33.                 c = constants[(int)*++ops];
  34.                 break;
  35.             case OP_SWP:
  36.                 tmp = a;
  37.                 a = x;
  38.                 x = tmp;
  39.                 break;
  40.         }
  41.     }
  42. }
  43.  
  44. static char *
  45. compile_word(char *ops, const char *word)
  46. {
  47.     int len = strlen(word);
  48.     *ops++ = OP_LDI;
  49.     *ops++ = len - 1;
  50.     for (int i = 0; i < len; i++) {
  51.         *ops++ = OP_LDC;
  52.         *ops++ = word[i] - 'A';
  53.         *ops++ = OP_MAD;
  54.     }
  55.     return ops;
  56. }
  57.  
  58. void
  59. disassemble(char *ops)
  60. {
  61.     for (;; ops++) {
  62.         switch ((enum op)*ops) {
  63.             case OP_RET:
  64.                 puts("ret");
  65.                 return;
  66.             case OP_MAD:
  67.                 puts("mad");
  68.                 break;
  69.             case OP_LDI:
  70.                 printf("ldi %d\n", *++ops);
  71.                 break;
  72.             case OP_LDC:
  73.                 printf("ldc %c\n", 'A' + *++ops);
  74.                 break;
  75.             case OP_SWP:
  76.                 puts("swp");
  77.                 break;
  78.             default:
  79.                 printf("INVALID:%d\n", *ops);
  80.         }
  81.     }
  82. }
  83.  
  84. static long
  85. solve(const char *vars, const char *ops, long *constants, unsigned avail)
  86. {
  87.     int v = *vars;
  88.     if (!v) {
  89.         return execute(ops, constants);
  90.     } else {
  91.         for (int i = 0; i < 10; i++) {
  92.             unsigned bit = 1u << i;
  93.             if (avail & bit) {
  94.                 constants[v - 'A'] = i;
  95.                 long r = solve(vars + 1, ops, constants, avail & ~bit);
  96.                 if (r)
  97.                     return r;
  98.             }
  99.         }
  100.     }
  101.     return 0;
  102. }
  103.  
  104. int
  105. main(void)
  106. {
  107.     char line[4096];
  108.     fgets(line, sizeof(line), stdin);
  109.  
  110.     /* Compiled representation of the puzzle */
  111.     char vars[11] = {0};
  112.     int nvars = 0;
  113.     static char program[1024UL * 1024];
  114.  
  115.     /* Compile puzzle into a program */
  116.     char seen[26] = {0};
  117.     char *ops = program;
  118.     for (char *tok = strtok(line, DELIM); tok; tok = strtok(0, DELIM)) {
  119.         switch (tok[0]) {
  120.             case '+':
  121.                 break;
  122.             case '=':
  123.                 *ops++ = OP_SWP;
  124.                 break;
  125.             default:
  126.                 for (char *c = tok; *c; c++) {
  127.                     int i = *c - 'A';
  128.                     if (!seen[i]) {
  129.                         seen[i] = 1;
  130.                         vars[nvars++] = *c;
  131.                     }
  132.                 }
  133.                 ops = compile_word(ops, tok);
  134.                 break;
  135.         }
  136.     }
  137.     *ops = OP_RET;
  138.     //disassemble(program);
  139.  
  140.     /* Run solver */
  141.     long constants[26] = {0};
  142.     if (solve(vars, program, constants, -1U))
  143.         for (char *v = vars; *v; v++)
  144.             printf("%c:%ld%c", *v, constants[*v - 'A'], " \n"[!v[1]]);
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement