#include #include #include #include #include #include "../../lib/aoc.h" #define PROGRAM_LENGTH 16 typedef struct Computer { long a; long b; long c; long program[PROGRAM_LENGTH]; int pc; long output[1000]; int output_count; } Computer; long combo(Computer *c, int operand) { switch (operand) { case 0: case 1: case 2: case 3: return operand; case 4: return c->a; case 5: return c->b; case 6: return c->c; default: printf("Invalid operand %d detected\n", operand); exit(1); } } void step(Computer *c) { int instruction = c->program[c->pc++]; int operand = c->program[c->pc++]; // printf("%d|%d\n", instruction, operand); // printf("a: %d, b: %d, c: %d, pc: %d\n", c->a, c->b, c->c, c->pc); switch(instruction) { case 0: // printf("0: a = %d / %d = %d\n", c->a, 1<a / (1<a = c->a / (1 << combo(c, operand)); break; case 1: // printf("1: b = %d ^ %d = %d\n", c->b, operand, c->b ^ operand); c->b = operand ^ c->b; break; case 2: // printf("2: b = %d % 8 = %d\n", combo(c, operand), combo(c, operand) % 8); c->b = combo(c, operand) % 8; break; case 3: // printf("3: if %d then jump to %d\n", c->a, operand); if (c->a) c->pc = operand; break; case 4: // printf("4: b = %d ^ %d = %d\n", c->b, c->c, c->b ^ c->c); c->b = c->b ^ c->c; break; case 5: // printf("5: print %d\n", combo(c, operand) % 8); c->output[c->output_count++] = combo(c, operand) % 8; break; case 6: // printf("6: b = %d / %d = %d\n", c->b, 1<b / (1<b = c->a / (1 << combo(c, operand)); break; case 7: // printf("7: c = %d / %d = %d\n", c->a, 1<a / (1<c = c->a / (1 << combo(c, operand)); break; } } bool quine(Computer *c, long a) { if (a % 100000000 == 0) printf("%ld\n", a); c->a = a; c->b = 0; c->c = 0; c->pc = 0; c->output_count = 0; while (c->pc < PROGRAM_LENGTH) { step(c); if (c->output_count == 0) continue; if (c->output[c->output_count - 1] != c->program[c->output_count - 1]) return false; } if (c->output_count != PROGRAM_LENGTH) return false; for (int i = 0; i < c->output_count; c++) { if (c->program[i] != c->output[i]) return false; } return true; } int main() { printf("%s\n", aoc_read_input()); Computer c; c.pc = 0; sscanf(aoc_read_line(), "Register A: %d", &(c.a)); sscanf(aoc_read_line(), "Register B: %d", &(c.b)); sscanf(aoc_read_line(), "Register C: %d", &(c.c)); aoc_read_line(); strtok(aoc_read_line(), " "); for (char *token = strtok(NULL, ","); token != NULL; token = strtok(NULL, ",")) { c.program[c.pc++] = atoi(token); } c.pc = 0; c.output_count = 0; while (c.pc < PROGRAM_LENGTH) { printf("a: %d, b: %d, c: %d, pc: %d\n", c.a, c.b, c.c, c.pc); step(&c); // printf("\n"); } printf("Part 1: %d", c.output[0]); for (int i = 1; i < c.output_count; i++) { printf(",%d", c.output[i]); } printf("\n"); //long a = 100000000000000; // long a = 8 ** 15; // long a = 2 ** 45; long a = 1l << 45l; for (; a < (1l << 48l); a++) { quine(&c, a); /*printf("%ld: ", a); for (int i = 0; i < c.output_count; i++) { printf("%ld,", c.output[i]); } printf("\n");*/ } // while (!quine(&c, a)) a++; printf("Part 2: %ld", a); aoc_free(); exit(0); }