diff --git a/c/2019/5/sunny_with_a_chance_of_asteroids.c b/c/2019/5/sunny_with_a_chance_of_asteroids.c new file mode 100644 index 0000000..9cccce1 --- /dev/null +++ b/c/2019/5/sunny_with_a_chance_of_asteroids.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#include "../../lib/intcode.h" + +int main() { + ic_load_rom_from_input(); + + IC *c = ic_new_computer(); + ic_run(c); + + printf("Part 1: %d\n", c->output_buffer[c->output_buffer_count - 1]); + // printf("Part 2: %d\n", noun * 100 + verb); + + aoc_free(); + return 0; +} diff --git a/c/lib/intcode.h b/c/lib/intcode.h index 718830d..646c23c 100644 --- a/c/lib/intcode.h +++ b/c/lib/intcode.h @@ -2,6 +2,10 @@ #include "./aoc.h" #define ROM_LENGTH 1000 +#define OUTPUT_BUFFER_LENGTH 1000 + +#define POSITION_MODE 0 +#define IMMEDIATE_MODE 1 int rom[ROM_LENGTH]; int rom_count; @@ -11,6 +15,8 @@ typedef struct IC { int *data; int program_counter; bool halted; + int output_buffer[OUTPUT_BUFFER_LENGTH]; + int output_buffer_count; } IC; int ic_peek(IC *c, int address) { @@ -33,54 +39,105 @@ void ic_halt(IC *c) { c->halted = true; } -void ic_instruction_add(IC *c) { +void ic_instruction_add(IC *c, int modes) { + bool x_mode = modes % 10; + modes /= 10; + bool y_mode = modes % 10; + modes /= 10; + int x = ic_read(c); + if (x_mode == POSITION_MODE) x = ic_peek(c, x); int y = ic_read(c); - ic_write(c, ic_peek(c, x) + ic_peek(c, y)); + if (y_mode == POSITION_MODE) y = ic_peek(c, y); + + ic_write(c, x + y); } -void ic_instruction_multiply(IC *c) { +void ic_instruction_multiply(IC *c, int modes) { + bool x_mode = modes % 10; + modes /= 10; + bool y_mode = modes % 10; + modes /= 10; + int x = ic_read(c); + if (x_mode == POSITION_MODE) x = ic_peek(c, x); int y = ic_read(c); - ic_write(c, ic_peek(c, x) * ic_peek(c, y)); + if (y_mode == POSITION_MODE) y = ic_peek(c, y); + + ic_write(c, x * y); } -void ic_instruction_halt(IC *c) { +void ic_instruction_input(IC *c, int _modes) { + ic_write(c, 1); +} + +void ic_instruction_output(IC *c, int modes) { + if (c->output_buffer_count >= OUTPUT_BUFFER_LENGTH) { + printf("Output buffer overflow!\n"); + ic_halt(c); + } + + int mode = modes % 10; + modes /= 10; + int to_output = ic_read(c); + if (mode == POSITION_MODE) to_output = ic_peek(c, to_output); + c->output_buffer[c->output_buffer_count++] = to_output; +} + +void ic_instruction_halt(IC *c, int _modes) { ic_halt(c); } int ic_execute_instruction(IC *c) { - int opcode = ic_read(c); + int instruction = ic_read(c); + int opcode = instruction % 100; + int modes = instruction / 100; + // printf("Running %d: opcode %d with modes %d\n", instruction, opcode, modes); + // printf("PC: %d\n", c->program_counter - 1); switch(opcode) { case 1: - ic_instruction_add(c); + ic_instruction_add(c, modes); break; case 2: - ic_instruction_multiply(c); + ic_instruction_multiply(c, modes); + break; + case 3: + ic_instruction_input(c, modes); + break; + case 4: + ic_instruction_output(c, modes); break; case 99: - ic_instruction_halt(c); + ic_instruction_halt(c, modes); break; default: printf("Invalid opcode [%d] encountered at %d\n", opcode, c->program_counter - 1); - ic_instruction_halt(c); + ic_instruction_halt(c, 0); 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"); + + printf("Output buffer: "); + for (int i = 0; i < c->output_buffer_count; i++) { + printf("[%d] ", c->output_buffer[i]); + } + printf("\n"); } void ic_reset(IC *c) { memcpy(c->data, c->rom, rom_count * sizeof(int)); c->program_counter = 0; c->halted = true; + c->output_buffer_count = 0; } void ic_run(IC *c) {