Advertisement
Guest User

solve.c

a guest
Jan 10th, 2018
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.40 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_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 char *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.                 c = constants[(int)*++ops];
  27.                 a += pow10[b] * c;
  28.                 b--;
  29.                 break;
  30.             case OP_LDI:
  31.                 b = *++ops;
  32.                 break;
  33.             case OP_SWP:
  34.                 tmp = a;
  35.                 a = x;
  36.                 x = tmp;
  37.                 break;
  38.         }
  39.     }
  40. }
  41.  
  42. static char *
  43. compile_word(char *ops, const char *word)
  44. {
  45.     *ops++ = OP_LDI;
  46.     char *imm8 = ops++;
  47.     int len = 0;
  48.     for (const char *c = word; *c; c++, len++) {
  49.         *ops++ = OP_MAD;
  50.         *ops++ = *c - 'A';
  51.     }
  52.     *imm8 = len - 1;
  53.     return ops;
  54. }
  55.  
  56. void
  57. disassemble(char *ops)
  58. {
  59.     for (;; ops++) {
  60.         switch ((enum op)*ops) {
  61.             case OP_RET:
  62.                 puts("ret");
  63.                 return;
  64.             case OP_MAD:
  65.                 printf("mad %c\n", 'A' + *++ops);
  66.                 break;
  67.             case OP_LDI:
  68.                 printf("ldi %d\n", *++ops);
  69.                 break;
  70.             case OP_SWP:
  71.                 puts("swp");
  72.                 break;
  73.         }
  74.     }
  75. }
  76.  
  77. static void
  78. solve(const char *vars, const char *ops, char *constants, unsigned avail)
  79. {
  80.     int v = *vars;
  81.     if (!v) {
  82.         if (execute(ops, constants)) {
  83.             for (int i = 0; i < 26; i++)
  84.                 if (constants[i] != 11)
  85.                     printf("%c:%d ", i + 'A', constants[i]);
  86.             putchar('\n');
  87.         }
  88.     } else {
  89.         for (int i = 0; i < 10; i++) {
  90.             unsigned bit = 1u << i;
  91.             if (avail & bit) {
  92.                 constants[v - 'A'] = i;
  93.                 solve(vars + 1, ops, constants, avail & ~bit);
  94.             }
  95.         }
  96.     }
  97. }
  98.  
  99. int
  100. main(void)
  101. {
  102.     char line[4096];
  103.     fgets(line, sizeof(line), stdin);
  104.  
  105.     /* Compiled representation of the puzzle */
  106.     char constants[26] = {
  107.         11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  108.         11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  109.     };
  110.     char program[4096];
  111.  
  112.     /* Compile puzzle into a program */
  113.     int nvars = 0;
  114.     char vars[11] = {0};
  115.     char *ops = program;
  116.     unsigned long seen = 0;
  117.     for (char *tok = strtok(line, DELIM); tok; tok = strtok(0, DELIM)) {
  118.         switch (tok[0]) {
  119.             case '+':
  120.                 break;
  121.             case '=':
  122.                 *ops++ = OP_SWP;
  123.                 break;
  124.             default:
  125.                 for (char *c = tok; *c; c++) {
  126.                     int i = *c - 'A';
  127.                     unsigned long bit = 1UL << i;
  128.                     if (!(seen & bit)) {
  129.                         seen |= bit;
  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.     solve(vars, program, constants, -1U);
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement