aoc_omni/c/2020/8/main.c
2025-11-30 21:22:21 -05:00

178 lines
3.8 KiB
C

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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());
}