#include #include #include #include #include "../lib/util.h" #define NUM_INSTRUCTIONS 654 typedef enum InstructionType { NOP, ACC, JMP } InstructionType; typedef struct Instruction { InstructionType type; int argument; } Instruction; typedef struct Console { size_t pc; int acc; Instruction program[NUM_INSTRUCTIONS]; bool visited_instructions[NUM_INSTRUCTIONS]; } Console; void parse_instruction(char *text, Instruction *i) { switch (*text) { case 'n': i->type = NOP; break; case 'a': i->type = ACC; break; case 'j': i->type = JMP; break; default: fprintf(stderr, "FATAL: Illegal instruction %s\n", text); exit(1); } i->argument = atoi(text + 4); } void console_step(Console *console) { Instruction i = console->program[console->pc]; switch(i.type) { case NOP: console->pc++; break; case ACC: console->pc++; console->acc += i.argument; break; case JMP: console->pc += i.argument; break; } } void console_print(Console *console) { printf("PC: %d, acc: %d\n", console->pc, console->acc); } void console_reset(Console *console) { console->acc = 0; console->pc = 0; } void console_run_until_loop(Console *console) { for (int i = 0; i < NUM_INSTRUCTIONS; i++) { console->visited_instructions[i] = false; } while (!console->visited_instructions[console->pc]) { console->visited_instructions[console->pc] = true; console_step(console); } } // true = overflow bool console_run_until_loop_or_overflow(Console *console) { for (int i = 0; i < NUM_INSTRUCTIONS; i++) { console->visited_instructions[i] = false; } while (!console->visited_instructions[console->pc]) { console->visited_instructions[console->pc] = true; console_step(console); if (console->pc >= NUM_INSTRUCTIONS) return true; } return false; } bool console_is_current_instruction_corrupted(Console *console) { Instruction i = console->program[console->pc]; printf("%d\n", i.type); fflush(stdout); switch(i.type) { case NOP: return console->pc + i.argument > NUM_INSTRUCTIONS - 7; case ACC: return false; case JMP: return console->pc == NUM_INSTRUCTIONS || console->pc == 648; } } void console_run_until_corruption(Console *console) { int corruption_index = 0; for (int i = 0; i < NUM_INSTRUCTIONS; i++) { Instruction *inst = &(console->program[i]); if (inst->type == ACC) continue; if (inst->type == NOP) { inst->type = JMP; if (console_run_until_loop_or_overflow(console)) return; inst->type = NOP; console_reset(console); } else { inst->type = NOP; if (console_run_until_loop_or_overflow(console)) return; inst->type = JMP; console_reset(console); } } } int part_1() { Console *console = malloc(sizeof(Console)); console_reset(console); char *data_buffer = load_input(); char *instruction_text = strtok(data_buffer, "\n"); do { Instruction *inst = &(console->program[console->pc++]); parse_instruction(instruction_text, inst); } while (instruction_text = strtok(NULL, "\n")); console_reset(console); console_run_until_loop(console); int answer = console->acc; free(console); free(data_buffer); return answer; } int part_2() { Console *console = malloc(sizeof(Console)); console_reset(console); char *data_buffer = load_input(); char *instruction_text = strtok(data_buffer, "\n"); console_reset(console); do { Instruction *inst = &(console->program[console->pc++]); parse_instruction(instruction_text, inst); } while (instruction_text = strtok(NULL, "\n")); console_reset(console); console_run_until_corruption(console); int answer = console->acc; free(console); free(data_buffer); return answer; } int main() { printf("Part 1: %d\n", part_1()); printf("Part 2: %d\n", part_2()); }