diff --git a/c/2019/2/1202_program_alarm.c b/c/2019/2/1202_program_alarm.c new file mode 100644 index 0000000..b9a6fb2 --- /dev/null +++ b/c/2019/2/1202_program_alarm.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +#include "../../lib/intcode.h" + +#define EXPECTED_OUTPUT 19690720 + +int main() { + ic_load_rom_from_input(); + + IC *c = ic_new_computer(); + ic_poke(c, 1, 12); + ic_poke(c, 2, 2); + ic_run(c); + + printf("Part 1: %d\n", ic_peek(c, 0)); + + int noun, verb; + for (noun = 0; noun < 100; noun++) { + for (verb = 0; verb < 100; verb++) { + ic_reset(c); + ic_poke(c, 1, noun); + ic_poke(c, 2, verb); + ic_run(c); + if (ic_peek(c, 0) == EXPECTED_OUTPUT) goto done; + } + } + done: + + printf("Part 2: %d\n", noun * 100 + verb); + + aoc_free(); + return 0; +} diff --git a/c/lib/intcode.h b/c/lib/intcode.h new file mode 100644 index 0000000..718830d --- /dev/null +++ b/c/lib/intcode.h @@ -0,0 +1,109 @@ +#include +#include "./aoc.h" + +#define ROM_LENGTH 1000 + +int rom[ROM_LENGTH]; +int rom_count; + +typedef struct IC { + int *rom; + int *data; + int program_counter; + bool halted; +} IC; + +int ic_peek(IC *c, int address) { + return c->data[address]; +} + +void ic_poke(IC *c, int address, int value) { + c->data[address] = value; +} + +int ic_read(IC *c) { + return ic_peek(c, c->program_counter++); +} + +void ic_write(IC *c, int value) { + ic_poke(c, ic_peek(c, c->program_counter++), value); +} + +void ic_halt(IC *c) { + c->halted = true; +} + +void ic_instruction_add(IC *c) { + int x = ic_read(c); + int y = ic_read(c); + ic_write(c, ic_peek(c, x) + ic_peek(c, y)); +} + +void ic_instruction_multiply(IC *c) { + int x = ic_read(c); + int y = ic_read(c); + ic_write(c, ic_peek(c, x) * ic_peek(c, y)); +} + +void ic_instruction_halt(IC *c) { + ic_halt(c); +} + +int ic_execute_instruction(IC *c) { + int opcode = ic_read(c); + switch(opcode) { + case 1: + ic_instruction_add(c); + break; + case 2: + ic_instruction_multiply(c); + break; + case 99: + ic_instruction_halt(c); + break; + default: + printf("Invalid opcode [%d] encountered at %d\n", opcode, c->program_counter - 1); + ic_instruction_halt(c); + break; + } +} + +void ic_print(IC *c) { + printf("PC: %d\n", c->program_counter); + for (int i = 0; i < rom_count; i++) { + printf("%6d ", c->data[i]); + if (i % 8 == 7) printf("\n"); + } + printf("\n"); +} + +void ic_reset(IC *c) { + memcpy(c->data, c->rom, rom_count * sizeof(int)); + c->program_counter = 0; + c->halted = true; +} + +void ic_run(IC *c) { + c->halted = false; + while (!c->halted) ic_execute_instruction(c); +} + +IC *ic_new_computer(void) { + IC *c = malloc(sizeof(IC)); + c->rom = rom; + c->data = malloc(rom_count * sizeof(int)); + ic_reset(c); + return c; +} + +int ic_load_rom_from_input(void) { + char *input = aoc_read_input(); + + char *token = strtok(input, ","); + while (token != NULL) { + rom[rom_count++] = atoi(token); + token = strtok(NULL, ","); + } + + return rom_count; +}