commit 0ba2f1d3d01cec0e51ccbe6b144009a7440f7b7b
parent 3ef16bed60d82e4d87ba93d90c891615d4078d87
Author: Louis Burda <quent.burda@gmail.com>
Date: Wed, 3 Nov 2021 01:15:53 +0100
Add day 5 part 1
Diffstat:
16 files changed, 542 insertions(+), 167 deletions(-)
diff --git a/data/helper/template/Makefile b/data/helper/template/Makefile
@@ -9,4 +9,4 @@ clean:
lib:
make -C ../../libs
-main: main.c
+main: main.c ../../libs/build/libaoc.so
diff --git a/libs/Makefile b/libs/Makefile
@@ -15,7 +15,7 @@ build/%.o: src/%.c include/%.h | build
build/wrapper.o: src/wrapper.c
$(CC) -c -o $@ $< $(CFLAGS) $(LDLIBS)
-build/libaoc.a: build/util.o build/aoc.o build/wrapper.o
+build/libaoc.a: build/util.o build/aoc.o build/wrapper.o build/memvec.o build/icc.o
ar rcs $@ $^
build/test_%: tests/%.c
diff --git a/libs/include/icc.h b/libs/include/icc.h
@@ -0,0 +1,52 @@
+#include "aoc.h"
+#include "util.h"
+#include "memvec.h"
+
+#include <stdlib.h>
+
+enum {
+ ICC_PARAM_IMM,
+ ICC_PARAM_POS
+};
+
+enum {
+ ICC_INST_ADD = 1,
+ ICC_INST_MULT = 2,
+ ICC_INST_STORE = 3,
+ ICC_INST_LOAD = 4,
+
+ ICC_INST_HALT = 99
+};
+
+enum {
+ ICC_OK,
+ ICC_INPUT,
+ ICC_OUTPUT,
+ ICC_HALT
+};
+
+struct icc {
+ int status;
+ int in, out;
+
+ size_t instp;
+ struct memvec instructions;
+};
+
+int icc_init(struct icc *icc);
+void icc_free(struct icc *icc);
+
+int icc_parse_inst(struct icc *icc, const char *str, size_t len);
+void icc_step_inst(struct icc *icc);
+
+void icc_set_inst(struct icc *icc, size_t addr, int in);
+void icc_get_inst(struct icc *icc, size_t addr, int *out);
+
+int icc_param_mode(int inst, int param);
+void icc_get_param(struct icc *icc, int param, int *out);
+void icc_get_dest(struct icc *icc, int param, int *out);
+
+void icc_input_callback(struct icc *icc, int (*callback)(int));
+
+void * icc_inst_copy(struct icc *icc);
+void icc_reset(struct icc *icc, void *instcopy);
diff --git a/src/day2/memvec.h b/libs/include/memvec.h
diff --git a/libs/include/util.h b/libs/include/util.h
@@ -13,6 +13,8 @@
#define ASSERT(expr) assert(expr, \
"Assert '" #expr "' at " LOC() " failed\n")
+#define ASSERTV(expr, msg, ...) assert(expr, \
+ LOC() " : " msg "\n" __VA_OPT__(,) __VA_ARGS__)
#define CHKP(ptr) chkp(ptr, \
"Unexpected NULL pointer '" #ptr "' at " LOC() "\n")
diff --git a/libs/src/icc.c b/libs/src/icc.c
@@ -0,0 +1,239 @@
+#include "icc.h"
+
+int
+icc_init(struct icc *icc)
+{
+ icc->instp = 0;
+ icc->status = ICC_OK;
+ return memvec_init(&icc->instructions, 0, sizeof(int));
+}
+
+void
+icc_free(struct icc *icc)
+{
+ memvec_free(&icc->instructions);
+}
+
+int
+icc_parse_inst(struct icc *icc, const char *str, size_t len)
+{
+ const char *line = str, *nline, *end = str + len;
+ char *endptr = NULL;
+ size_t linelen;
+ int val;
+
+ do {
+ nline = ntoken(line, end, &linelen, ",\n");
+ val = strtoul(line, &endptr, 10);
+ if (endptr && !memchr(",\n", *endptr, 3))
+ return FAIL;
+ if (memvec_add(&icc->instructions, &val) == FAIL)
+ return FAIL;
+ line = nline;
+ } while (nline);
+
+ return OK;
+}
+
+const char*
+icc_param_str(struct icc *icc, int param)
+{
+ static char buf[32];
+ int val;
+
+ icc_get_inst(icc, icc->instp + param, &val);
+ snprintf(buf, sizeof(buf), "%i", val);
+
+ return buf;
+}
+
+void
+icc_debug_op(struct icc *icc, const char *opstr, int n)
+{
+ int i, val, inst;
+
+ if (!aoc.debug) return;
+
+ icc_get_inst(icc, icc->instp, &inst);
+
+ fprintf(stderr, "%04li: (%05i) %s ", icc->instp, inst, opstr);
+
+ for (i = 1; i <= n; i++) {
+ if (i > 1) fprintf(stderr, ", ");
+ icc_get_inst(icc, icc->instp + i, &val);
+ switch (icc_param_mode(inst, i)) {
+ case ICC_PARAM_IMM:
+ fprintf(stderr, "%i", val);
+ break;
+ case ICC_PARAM_POS:
+ fprintf(stderr, "[%i]", val);
+ break;
+ default:
+ die("ICC: Unknown parmeter mode\n");
+ }
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void
+icc_inst_add(struct icc *icc)
+{
+ int a, b, dst;
+
+ icc_get_param(icc, 1, &a);
+ icc_get_param(icc, 2, &b);
+ icc_get_dest(icc, 3, &dst);
+
+ icc_debug_op(icc, "ADD", 3);
+ icc_set_inst(icc, dst, a + b);
+
+ icc->instp += 4;
+ icc->status = ICC_OK;
+}
+
+void
+icc_inst_mul(struct icc *icc)
+{
+ int a, b, dst;
+
+ icc_get_param(icc, 1, &a);
+ icc_get_param(icc, 2, &b);
+ icc_get_dest(icc, 3, &dst);
+
+ icc_debug_op(icc, "MUL", 3);
+ icc_set_inst(icc, dst, a * b);
+
+ icc->instp += 4;
+ icc->status = ICC_OK;
+}
+
+void
+icc_inst_store(struct icc *icc)
+{
+ int dst;
+
+ if (icc->status != ICC_INPUT) {
+ icc_debug_op(icc, "INPUT", 0);
+ icc->status = ICC_INPUT;
+ } else {
+ icc_debug_op(icc, "STORE", 1);
+ icc_get_dest(icc, 1, &dst);
+ icc_set_inst(icc, dst, icc->in);
+
+ icc->instp += 2;
+ icc->status = ICC_OK;
+ }
+}
+
+void
+icc_inst_load(struct icc *icc)
+{
+ int out;
+
+ if (icc->status != ICC_OUTPUT) {
+ icc_debug_op(icc, "LOAD", 1);
+ icc_get_param(icc, 1, &out);
+
+ icc->out = out;
+ icc->status = ICC_OUTPUT;
+ icc_debug_op(icc, "OUTPUT", 0);
+ } else {
+ icc->instp += 2;
+ icc->status = ICC_OK;
+ }
+}
+
+void
+icc_step_inst(struct icc *icc)
+{
+ int inst;
+
+ icc_get_inst(icc, icc->instp, &inst);
+ inst %= 100;
+
+ switch (inst) {
+ case ICC_INST_ADD:
+ icc_inst_add(icc);
+ break;
+ case ICC_INST_MULT:
+ icc_inst_mul(icc);
+ break;
+ case ICC_INST_STORE:
+ icc_inst_store(icc);
+ break;
+ case ICC_INST_LOAD:
+ icc_inst_load(icc);
+ break;
+ case ICC_INST_HALT:
+ icc->status = ICC_HALT;
+ break;
+ default:
+ die("ICC: Unknown instruction: '%i'\n", inst);
+ }
+}
+
+void
+icc_set_inst(struct icc *icc, size_t addr, int val)
+{
+ memvec_set(&icc->instructions, addr, &val);
+}
+
+void
+icc_get_inst(struct icc *icc, size_t addr, int *out)
+{
+ *out = *(int*)memvec_get(&icc->instructions, addr);
+}
+
+int
+icc_param_mode(int inst, int param)
+{
+ int div, i;
+
+ div = 100;
+ for (i = 1; i < param; i++) div *= 10;
+
+ return (inst / div) % 10 == 1 ? ICC_PARAM_IMM : ICC_PARAM_POS;
+}
+
+void
+icc_get_param(struct icc *icc, int param, int *out)
+{
+ int inst, val;
+
+ icc_get_inst(icc, icc->instp, &inst);
+ icc_get_inst(icc, icc->instp + param, &val);
+
+ switch (icc_param_mode(inst, param)) {
+ case ICC_PARAM_IMM:
+ *out = val;
+ break;
+ case ICC_PARAM_POS:
+ icc_get_inst(icc, val, out);
+ break;
+ default:
+ die("ICC: Unknown parmeter mode\n");
+ };
+}
+
+void
+icc_get_dest(struct icc *icc, int param, int *out)
+{
+ icc_get_inst(icc, icc->instp + param, out);
+}
+
+void*
+icc_inst_copy(struct icc *icc)
+{
+ return memdup(icc->instructions.data, icc->instructions.len);
+}
+
+void
+icc_reset(struct icc *icc, void *instcopy)
+{
+ icc->status = ICC_OK;
+ icc->instp = 0;
+ if (instcopy)
+ memcpy(icc->instructions.data, instcopy, icc->instructions.len);
+}
+
diff --git a/src/day2/memvec.c b/libs/src/memvec.c
diff --git a/src/day2/Makefile b/src/day2/Makefile
@@ -1,4 +1,4 @@
-CFLAGS = -I ../../libs/include -L ../../libs/build -g
+CFLAGS = -g -I ../../libs/include -L ../../libs/build
LDLIBS = -laoc
all: lib main
@@ -9,5 +9,4 @@ lib:
clean:
rm main
-main: *.c *.h
- $(CC) -o $@ *.c $(CFLAGS) $(LDLIBS)
+main: main.c ../../libs/build/libaoc.a
diff --git a/src/day2/icc.c b/src/day2/icc.c
@@ -1,108 +0,0 @@
-#include "icc.h"
-
-int
-icc_init(struct icc *config)
-{
- config->instp = 0;
- config->status = ICC_OK;
- return memvec_init(&config->instructions, 0, sizeof(int));
-}
-
-void
-icc_free(struct icc *config)
-{
- memvec_free(&config->instructions);
-}
-
-int
-icc_parse_inst(struct icc *config, const char *str, size_t len)
-{
- const char *line = str, *nline, *end = str + len;
- char *endptr = NULL;
- size_t linelen;
- int val;
-
- do {
- nline = ntoken(line, end, &linelen, ",\n");
- val = strtoul(line, &endptr, 10);
- if (endptr && !memchr(",\n", *endptr, 3))
- return FAIL;
- if (memvec_add(&config->instructions, &val) == FAIL)
- return FAIL;
- line = nline;
- } while (nline);
-
- return OK;
-}
-
-void
-icc_inst_add(struct icc *config)
-{
- int a, b, res, dst;
- a = ICC_GET_INST(config, config->instp + 1);
- b = ICC_GET_INST(config, config->instp + 2);
- res = ICC_GET_INST(config, a)
- + ICC_GET_INST(config, b);
- dst = ICC_GET_INST(config, config->instp + 3);
- debug("%i <= %i + %i\n", dst, a, b);
- memvec_set(&config->instructions, dst, &res);
- config->instp += 4;
-}
-
-void
-icc_inst_mul(struct icc *config)
-{
- int a, b, res, dst;
- a = ICC_GET_INST(config, config->instp + 1);
- b = ICC_GET_INST(config, config->instp + 2);
- res = ICC_GET_INST(config, a)
- * ICC_GET_INST(config, b);
- dst = ICC_GET_INST(config, config->instp + 3);
- debug("%i <= %i * %i\n", dst, a, b);
- memvec_set(&config->instructions, dst, &res);
- config->instp += 4;
-}
-
-void
-icc_step_inst(struct icc *config)
-{
- int inst;
-
- inst = ICC_GET_INST(config, config->instp);
-
- switch (inst) {
- case ICC_INST_ADD:
- icc_inst_add(config);
- break;
- case ICC_INST_MULT:
- icc_inst_mul(config);
- break;
- case ICC_INST_HALT:
- config->status = ICC_HALT;
- break;
- default:
- die("Hit unknown instruction: '%i'\n", inst);
- }
-}
-
-void
-icc_set_inst(struct icc *config, size_t index, int val)
-{
- memvec_set(&config->instructions, index, &val);
-}
-
-void*
-icc_inst_copy(struct icc *config)
-{
- return memdup(config->instructions.data, config->instructions.len);
-}
-
-void
-icc_reset(struct icc *config, void *instcopy)
-{
- config->status = ICC_OK;
- config->instp = 0;
- if (instcopy)
- memcpy(config->instructions.data, instcopy, config->instructions.len);
-}
-
diff --git a/src/day2/icc.h b/src/day2/icc.h
@@ -1,33 +0,0 @@
-#include "aoc.h"
-#include "util.h"
-#include "memvec.h"
-
-#include <stdlib.h>
-
-#define ICC_GET_INST(conf, addr) (*(int*)memvec_get(&(conf)->instructions, addr))
-
-enum {
- ICC_INST_ADD = 1,
- ICC_INST_MULT = 2,
- ICC_INST_HALT = 99
-};
-
-enum {
- ICC_OK,
- ICC_HALT
-};
-
-struct icc {
- int status;
- size_t instp;
- struct memvec instructions;
-};
-
-int icc_init(struct icc *config);
-void icc_free(struct icc *config);
-int icc_parse_inst(struct icc *config, const char *str, size_t len);
-void icc_step_inst(struct icc *config);
-void icc_set_inst(struct icc *config, size_t index, int val);
-void* icc_inst_copy(struct icc *config);
-void icc_reset(struct icc *config, void *instcopy);
-
diff --git a/src/day2/main.c b/src/day2/main.c
@@ -7,54 +7,57 @@
void
part1(void)
{
- struct icc config;
+ struct icc icc;
+ int res;
- ASSERT(icc_init(&config) == OK);
- ASSERT(icc_parse_inst(&config, aoc.input, aoc.input_size) == OK);
+ ASSERT(icc_init(&icc) == OK);
+ ASSERT(icc_parse_inst(&icc, aoc.input, aoc.input_size) == OK);
- icc_set_inst(&config, 1, 12);
- icc_set_inst(&config, 2, 2);
+ icc_set_inst(&icc, 1, 12);
+ icc_set_inst(&icc, 2, 2);
- while (config.status != ICC_HALT)
- icc_step_inst(&config);
+ while (icc.status != ICC_HALT)
+ icc_step_inst(&icc);
- aoc.answer = CHKP(aprintf("%i", ICC_GET_INST(&config, 0)));
+ icc_get_inst(&icc, 0, &res);
+ aoc.answer = CHKP(aprintf("%i", res));
aoc.solution = "5098658";
- icc_free(&config);
+ icc_free(&icc);
}
void
part2(void)
{
- struct icc config;
+ struct icc icc;
void *instcopy;
- int a, b;
+ int a, b, c;
- ASSERT(icc_init(&config) == OK);
- ASSERT(icc_parse_inst(&config, aoc.input, aoc.input_size) == OK);
- instcopy = icc_inst_copy(&config);
+ ASSERT(icc_init(&icc) == OK);
+ ASSERT(icc_parse_inst(&icc, aoc.input, aoc.input_size) == OK);
+ instcopy = icc_inst_copy(&icc);
for (a = 0; a < 100; a++) {
for (b = 0; b < 100; b++) {
- icc_set_inst(&config, 1, a);
- icc_set_inst(&config, 2, b);
+ icc_set_inst(&icc, 1, a);
+ icc_set_inst(&icc, 2, b);
debug("\nTrying a:%i b:%i\n\n", a, b);
- while (config.status != ICC_HALT)
- icc_step_inst(&config);
+ while (icc.status != ICC_HALT)
+ icc_step_inst(&icc);
- if (ICC_GET_INST(&config, 0) == 19690720) {
+ icc_get_inst(&icc, 0, &c);
+ if (c == 19690720) {
aoc.answer = CHKP(aprintf("%02i%02i", a, b));
aoc.solution = "5064";
goto exit;
} else {
- icc_reset(&config, instcopy);
+ icc_reset(&icc, instcopy);
}
}
}
exit:
free(instcopy);
- icc_free(&config);
+ icc_free(&icc);
}
diff --git a/src/day5/Makefile b/src/day5/Makefile
@@ -0,0 +1,12 @@
+CFLAGS = -g -I ../../libs/include -L ../../libs/build
+LDLIBS = -laoc
+
+all: lib main
+
+clean:
+ rm main
+
+lib:
+ make -C ../../libs
+
+main: main.c ../../libs/build/libaoc.a
diff --git a/src/day5/input b/src/day5/input
@@ -0,0 +1 @@
+3,225,1,225,6,6,1100,1,238,225,104,0,1002,114,19,224,1001,224,-646,224,4,224,102,8,223,223,1001,224,7,224,1,223,224,223,1101,40,62,225,1101,60,38,225,1101,30,29,225,2,195,148,224,1001,224,-40,224,4,224,1002,223,8,223,101,2,224,224,1,224,223,223,1001,143,40,224,101,-125,224,224,4,224,1002,223,8,223,1001,224,3,224,1,224,223,223,101,29,139,224,1001,224,-99,224,4,224,1002,223,8,223,1001,224,2,224,1,224,223,223,1101,14,34,225,102,57,39,224,101,-3420,224,224,4,224,102,8,223,223,1001,224,7,224,1,223,224,223,1101,70,40,225,1102,85,69,225,1102,94,5,225,1,36,43,224,101,-92,224,224,4,224,1002,223,8,223,101,1,224,224,1,224,223,223,1102,94,24,224,1001,224,-2256,224,4,224,102,8,223,223,1001,224,1,224,1,223,224,223,1102,8,13,225,1101,36,65,224,1001,224,-101,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,8,677,226,224,1002,223,2,223,1006,224,329,1001,223,1,223,1108,226,226,224,1002,223,2,223,1005,224,344,101,1,223,223,1108,226,677,224,1002,223,2,223,1006,224,359,101,1,223,223,107,226,226,224,1002,223,2,223,1005,224,374,101,1,223,223,1107,226,226,224,1002,223,2,223,1005,224,389,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,404,101,1,223,223,1008,226,226,224,1002,223,2,223,1006,224,419,101,1,223,223,108,677,226,224,1002,223,2,223,1006,224,434,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,449,101,1,223,223,1008,677,226,224,102,2,223,223,1006,224,464,1001,223,1,223,108,677,677,224,102,2,223,223,1005,224,479,101,1,223,223,7,677,677,224,102,2,223,223,1005,224,494,1001,223,1,223,8,226,677,224,102,2,223,223,1006,224,509,101,1,223,223,107,677,226,224,1002,223,2,223,1005,224,524,1001,223,1,223,7,677,226,224,1002,223,2,223,1005,224,539,1001,223,1,223,1007,226,677,224,1002,223,2,223,1005,224,554,1001,223,1,223,8,677,677,224,102,2,223,223,1006,224,569,101,1,223,223,7,226,677,224,102,2,223,223,1006,224,584,1001,223,1,223,1008,677,677,224,102,2,223,223,1005,224,599,101,1,223,223,1007,677,677,224,1002,223,2,223,1006,224,614,101,1,223,223,1107,677,226,224,1002,223,2,223,1006,224,629,101,1,223,223,1107,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,226,226,224,102,2,223,223,1005,224,659,1001,223,1,223,108,226,226,224,102,2,223,223,1006,224,674,101,1,223,223,4,223,99,226
diff --git a/src/day5/main.c b/src/day5/main.c
@@ -0,0 +1,34 @@
+#include "aoc.h"
+#include "icc.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void
+part1(void)
+{
+ struct icc icc;
+
+ ASSERT(icc_init(&icc) == OK);
+ ASSERT(icc_parse_inst(&icc, aoc.input, aoc.input_size) == OK);
+
+ while (icc.status != ICC_HALT) {
+ icc_step_inst(&icc);
+ switch (icc.status) {
+ case ICC_INPUT:
+ icc.in = 1;
+ break;
+ case ICC_OUTPUT:
+ printf("%i\n", icc.out);
+ break;
+ }
+ }
+
+ icc_free(&icc);
+}
+
+void
+part2(void)
+{
+
+}
diff --git a/src/day5/part1 b/src/day5/part1
@@ -0,0 +1,98 @@
+--- Day 5: Sunny with a Chance of Asteroids ---
+
+You're starting to sweat as the ship makes its way toward Mercury. The Elves suggest that you get
+the air conditioner working by upgrading your ship computer to support the Thermal Environment
+Supervision Terminal.
+
+The Thermal Environment Supervision Terminal (TEST) starts by running a [1m[37mdiagnostic
+program[0m (your puzzle input). The TEST diagnostic program will run on your existing Intcode
+computer after a few modifications:
+
+[1m[37mFirst[0m, you'll need to add [1m[37mtwo new instructions[0m:
+
+
+ - Opcode 3 takes a single integer as [1m[37minput[0m and saves it to the position given by its
+only parameter. For example, the instruction 3,50 would take an input value and store it at address
+50.
+
+ - Opcode 4 [1m[37moutputs[0m the value of its only parameter. For example, the instruction 4,50
+would output the value at address 50.
+
+
+Programs that use these instructions will come with documentation that explains what should be
+connected to the input and output. The program 3,0,4,0,99 outputs whatever it gets as input, then
+halts.
+
+[1m[37mSecond[0m, you'll need to add support for [1m[37mparameter modes[0m:
+
+Each parameter of an instruction is handled based on its parameter mode. Right now, your ship
+computer already understands parameter mode 0, [1m[37mposition mode[0m, which causes the
+parameter to be interpreted as a [1m[37mposition[0m - if the parameter is 50, its value is
+[1m[37mthe value stored at address 50 in memory[0m. Until now, all parameters have been in
+position mode.
+
+Now, your ship computer will also need to handle parameters in mode 1, [1m[37mimmediate mode[0m.
+In immediate mode, a parameter is interpreted as a [1m[37mvalue[0m - if the parameter is 50, its
+value is simply [1m[37m50[0m.
+
+Parameter modes are stored in the same value as the instruction's opcode. The opcode is a two-digit
+number based only on the ones and tens digit of the value, that is, the opcode is the rightmost two
+digits of the first value in an instruction. Parameter modes are single digits, one per parameter,
+read right-to-left from the opcode: the first parameter's mode is in the hundreds digit, the second
+parameter's mode is in the thousands digit, the third parameter's mode is in the ten-thousands
+digit, and so on. Any missing modes are 0.
+
+For example, consider the program 1002,4,3,4,33.
+
+The first instruction, 1002,4,3,4, is a [1m[37mmultiply[0m instruction - the rightmost two digits
+of the first value, 02, indicate opcode 2, multiplication. Then, going right to left, the parameter
+modes are 0 (hundreds digit), 1 (thousands digit), and 0 (ten-thousands digit, not present and
+therefore zero):
+
+ABCDE
+ 1002
+
+DE - two-digit opcode, 02 == opcode 2
+ C - mode of 1st parameter, 0 == position mode
+ B - mode of 2nd parameter, 1 == immediate mode
+ A - mode of 3rd parameter, 0 == position mode,
+ omitted due to being a leading zero
+
+This instruction multiplies its first two parameters. The first parameter, 4 in position mode,
+works like it did before - its value is the value stored at address 4 (33). The second parameter, 3
+in immediate mode, simply has value 3. The result of this operation, 33 * 3 = 99, is written
+according to the third parameter, 4 in position mode, which also works like it did before - 99 is
+written to address 4.
+
+Parameters that an instruction writes to will [1m[37mnever be in immediate mode[0m.
+
+[1m[37mFinally[0m, some notes:
+
+
+ - It is important to remember that the instruction pointer should increase by [1m[37mthe number
+of values in the instruction[0m after the instruction finishes. Because of the new instructions,
+this amount is no longer always 4.
+
+ - Integers can be negative: 1101,100,-1,4,0 is a valid program (find 100 + -1, store the result in
+position 4).
+
+
+The TEST diagnostic program will start by requesting from the user the ID of the system to test by
+running an [1m[37minput[0m instruction - provide it 1, the ID for the ship's air conditioner
+unit.
+
+It will then perform a series of diagnostic tests confirming that various parts of the Intcode
+computer, like parameter modes, function correctly. For each test, it will run an
+[1m[37moutput[0m instruction indicating how far the result of the test was from the expected
+value, where 0 means the test was successful. Non-zero outputs mean that a function is not working
+correctly; check the instructions that were run before the output instruction to see which one
+failed.
+
+Finally, the program will output a [1m[37mdiagnostic code[0m and immediately halt. This final
+output isn't an error; an output followed immediately by a halt means the program finished. If all
+outputs were zero except the diagnostic code, the diagnostic program ran successfully.
+
+After providing 1 to the only input instruction and passing all the tests, [1m[37mwhat diagnostic
+code does the program produce?[0m
+
+
diff --git a/src/day5/part2 b/src/day5/part2
@@ -0,0 +1,76 @@
+--- Part Two ---
+
+The air conditioner comes online! Its cold air feels good for a while, but then the TEST alarms
+start to go off. Since the air conditioner can't vent its heat anywhere but back into the
+spacecraft, it's actually making the air inside the ship [1m[37mwarmer[0m.
+
+Instead, you'll need to use the TEST to extend the thermal radiators. Fortunately, the diagnostic
+program (your puzzle input) is already equipped for this. Unfortunately, your Intcode computer is
+not.
+
+Your computer is only missing a few opcodes:
+
+
+ - Opcode 5 is [1m[37mjump-if-true[0m: if the first parameter is [1m[37mnon-zero[0m, it sets
+the instruction pointer to the value from the second parameter. Otherwise, it does nothing.
+
+ - Opcode 6 is [1m[37mjump-if-false[0m: if the first parameter [1m[37mis zero[0m, it sets the
+instruction pointer to the value from the second parameter. Otherwise, it does nothing.
+
+ - Opcode 7 is [1m[37mless than[0m: if the first parameter is [1m[37mless than[0m the second
+parameter, it stores 1 in the position given by the third parameter. Otherwise, it stores 0.
+
+ - Opcode 8 is [1m[37mequals[0m: if the first parameter is [1m[37mequal to[0m the second
+parameter, it stores 1 in the position given by the third parameter. Otherwise, it stores 0.
+
+
+Like all instructions, these instructions need to support [1m[37mparameter modes[0m as described
+above.
+
+Normally, after an instruction is finished, the instruction pointer increases by the number of
+values in that instruction. [1m[37mHowever[0m, if the instruction modifies the instruction
+pointer, that value is used and the instruction pointer is [1m[37mnot automatically increased[0m.
+
+For example, here are several programs that take one input, compare it to the value 8, and then
+produce one output:
+
+
+ - 3,9,8,9,10,9,4,9,99,-1,8 - Using [1m[37mposition mode[0m, consider whether the input is
+[1m[37mequal to[0m 8; output 1 (if it is) or 0 (if it is not).
+
+ - 3,9,7,9,10,9,4,9,99,-1,8 - Using [1m[37mposition mode[0m, consider whether the input is
+[1m[37mless than[0m 8; output 1 (if it is) or 0 (if it is not).
+
+ - 3,3,1108,-1,8,3,4,3,99 - Using [1m[37mimmediate mode[0m, consider whether the input is
+[1m[37mequal to[0m 8; output 1 (if it is) or 0 (if it is not).
+
+ - 3,3,1107,-1,8,3,4,3,99 - Using [1m[37mimmediate mode[0m, consider whether the input is
+[1m[37mless than [0m8; output 1 (if it is) or 0 (if it is not).
+
+
+Here are some jump tests that take an input, then output 0 if the input was zero or 1 if the input
+was non-zero:
+
+
+ - 3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9 (using [1m[37mposition mode[0m)
+
+ - 3,3,1105,-1,9,1101,0,0,12,4,12,99,1 (using [1m[37mimmediate mode[0m)
+
+
+Here's a larger example:
+
+3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
+1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
+999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99
+
+The above example program uses an input instruction to ask for a single number. The program will
+then output 999 if the input value is below 8, output 1000 if the input value is equal to 8, or
+output 1001 if the input value is greater than 8.
+
+This time, when the TEST diagnostic program runs its input instruction to get the ID of the system
+to test, [1m[37mprovide it 5[0m, the ID for the ship's thermal radiator controller. This
+diagnostic test suite only outputs one number, the [1m[37mdiagnostic code[0m.
+
+[1m[37mWhat is the diagnostic code for system ID 5?[0m
+
+