From 6e9cf2c26a4967f079ea6db3597be840e82e2a3d Mon Sep 17 00:00:00 2001
From: Bill Rossi <bassguitarbill@gmail.com>
Date: Thu, 12 Dec 2024 11:05:54 -0500
Subject: [PATCH] C Intcode problem 2 part 1

---
 c/2019/5/sunny_with_a_chance_of_asteroids.c | 19 +++++
 c/lib/intcode.h                             | 77 ++++++++++++++++++---
 2 files changed, 86 insertions(+), 10 deletions(-)
 create mode 100644 c/2019/5/sunny_with_a_chance_of_asteroids.c

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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#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) {