From e8c883e374b5f4ec16721f2652447f53a91dd3e3 Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Fri, 11 Dec 2020 09:24:22 -0800
Subject: [PATCH 01/12] Restructured project and updated day 3

---
 2020/Makefile                                | 16 +++--
 2020/{ => days}/day1.cpp                     | 19 +++---
 2020/{ => days}/day10.cpp                    | 13 ++--
 2020/{ => days}/day11.cpp                    | 13 ++--
 2020/{ => days}/day2.cpp                     | 13 ++--
 2020/{ => days}/day3.cpp                     | 57 ++++++++++-------
 2020/{ => days}/day4.cpp                     | 12 ++--
 2020/{ => days}/day5.cpp                     | 13 ++--
 2020/{ => days}/day6.cpp                     | 12 ++--
 2020/{ => days}/day7.cpp                     | 13 ++--
 2020/{ => days}/day8.cpp                     | 13 ++--
 2020/{ => days}/day9.cpp                     | 13 ++--
 2020/{ => inputs}/day1.input                 |  0
 2020/{ => inputs}/day10.input                |  0
 2020/{ => inputs}/day11.input                |  0
 2020/{ => inputs}/day2.input                 |  0
 2020/{ => inputs}/day3.input                 |  0
 2020/{ => inputs}/day4.input                 |  0
 2020/{ => inputs}/day5.input                 |  0
 2020/{ => inputs}/day6.input                 |  0
 2020/{ => inputs}/day7.input                 |  0
 2020/{ => inputs}/day8.input                 |  0
 2020/{ => inputs}/day9.input                 |  0
 2020/{template.cpp => misc/day.cpp.template} |  9 ++-
 2020/misc/main.cpp                           | 36 +++++++++++
 2020/misc/main_test.cpp                      | 66 ++++++++++++++++++++
 2020/misc/print.hpp                          | 31 +++++++++
 2020/{ => misc}/types.cpp                    |  0
 2020/{ => misc}/types.hpp                    |  0
 29 files changed, 245 insertions(+), 104 deletions(-)
 rename 2020/{ => days}/day1.cpp (87%)
 rename 2020/{ => days}/day10.cpp (91%)
 rename 2020/{ => days}/day11.cpp (94%)
 rename 2020/{ => days}/day2.cpp (91%)
 rename 2020/{ => days}/day3.cpp (60%)
 rename 2020/{ => days}/day4.cpp (95%)
 rename 2020/{ => days}/day5.cpp (90%)
 rename 2020/{ => days}/day6.cpp (91%)
 rename 2020/{ => days}/day7.cpp (93%)
 rename 2020/{ => days}/day8.cpp (94%)
 rename 2020/{ => days}/day9.cpp (92%)
 rename 2020/{ => inputs}/day1.input (100%)
 rename 2020/{ => inputs}/day10.input (100%)
 rename 2020/{ => inputs}/day11.input (100%)
 rename 2020/{ => inputs}/day2.input (100%)
 rename 2020/{ => inputs}/day3.input (100%)
 rename 2020/{ => inputs}/day4.input (100%)
 rename 2020/{ => inputs}/day5.input (100%)
 rename 2020/{ => inputs}/day6.input (100%)
 rename 2020/{ => inputs}/day7.input (100%)
 rename 2020/{ => inputs}/day8.input (100%)
 rename 2020/{ => inputs}/day9.input (100%)
 rename 2020/{template.cpp => misc/day.cpp.template} (91%)
 create mode 100644 2020/misc/main.cpp
 create mode 100644 2020/misc/main_test.cpp
 create mode 100644 2020/misc/print.hpp
 rename 2020/{ => misc}/types.cpp (100%)
 rename 2020/{ => misc}/types.hpp (100%)

diff --git a/2020/Makefile b/2020/Makefile
index ede9575..812ac33 100644
--- a/2020/Makefile
+++ b/2020/Makefile
@@ -1,12 +1,16 @@
-day%.out: out/types.o day%.cpp
-	g++-10 -std=c++2a $(flags) $(@:out=cpp) out/types.o -o $@
+day%.out: out/types.o misc/main.cpp days/day%.cpp
+	g++-10 -std=c++2a $(flags) -Dcurrent_day=$(@:.out=) days/$(@:out=cpp) misc/main.cpp out/types.o -o $@
 
-day%.cpp:
-	cp template.cpp $@
+day%_test.out: out/types.o misc/main_test.cpp days/day%.cpp
+	g++-10 -std=c++2a $(flags) -DTEST_BUILD -Dcurrent_day=$(@:_test.out=) days/$(@:_test.out=.cpp) misc/main_test.cpp out/types.o -o $@
 
-out/types.o: types.hpp types.cpp
+days/day%.cpp:
+	cp 'misc/day.cpp.template' $@
+	sed -i -e "s/current_day/$(shell basename $@ | cut -f 1 -d '.')/g" $@
+
+out/types.o: misc/types.hpp misc/types.cpp
 	mkdir -p out/
-	g++-10 -std=c++2a $(flags) -c types.cpp -o $@
+	g++-10 -std=c++2a $(flags) -c misc/types.cpp -o $@
 
 .PHONY: clean
 clean:
diff --git a/2020/day1.cpp b/2020/days/day1.cpp
similarity index 87%
rename from 2020/day1.cpp
rename to 2020/days/day1.cpp
index 5eda877..03d3b48 100644
--- a/2020/day1.cpp
+++ b/2020/days/day1.cpp
@@ -30,7 +30,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 // Find 2 numbers that sum to 2020
 auto find_2020_x2(const std::vector<i32> & list) -> void {
@@ -44,7 +45,7 @@ auto find_2020_x2(const std::vector<i32> & list) -> void {
 			--end;
 		}
 	}
-	std::cout << (list[begin] * list[end]) << std::endl;
+	print((list[begin] * list[end]));
 }
 
 // Find 3 numbers that sum to 2020
@@ -53,13 +54,13 @@ auto find_2020_x3(const std::vector<i32> & list) -> void {
 		for (auto n1 = 1; n1 < list.size() - 1; ++n1) {
 			auto low  = n0 + 1;
 			auto high = n1;
-			auto n2   = (low + high) / 2;
-			while (low < high - 1) {
+			while (low < high) {
+				auto n2  = (low + high) / 2;
 				auto sum = 0;
 				if ((sum = list[n0] + list[n1] + list[n2]) == 2020) {
-					std::cout << (list[n0] * list[n1] * list[n2]) << std::endl;
+					print((list[n0] * list[n1] * list[n2]));
 					return;
-				} else if (sum > 2020) {
+				} else if (sum < 2020) {
 					low = n2 + 1;
 				} else {
 					high = n2;
@@ -69,11 +70,11 @@ auto find_2020_x3(const std::vector<i32> & list) -> void {
 	}
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day1() -> void {
 	auto list = std::vector<i32>();
 	{
 		auto line = std::string();
-		auto file = std::ifstream("day1.input");
+		auto file = std::ifstream("inputs/day1.input");
 		while (getline(file, line)) {
 			list.push_back(std::stoi(line));
 		}
@@ -82,6 +83,4 @@ auto main(i32 argc, char * argv[]) -> i32 {
 
 	find_2020_x2(list);
 	find_2020_x3(list);
-
-	return 0;
 }
diff --git a/2020/day10.cpp b/2020/days/day10.cpp
similarity index 91%
rename from 2020/day10.cpp
rename to 2020/days/day10.cpp
index 9f6fab4..0da5b83 100644
--- a/2020/day10.cpp
+++ b/2020/days/day10.cpp
@@ -29,7 +29,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 struct Pair {
 	u64 jolt;
@@ -40,11 +41,11 @@ auto operator<(const Pair & left, const Pair & right) -> bool {
 	return left.jolt < right.jolt;
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day10() -> void {
 	auto jolts = std::vector<Pair>{{ 0, 1 }};
 	{
 		auto line = std::string();
-		auto file = std::ifstream("day10.input");
+		auto file = std::ifstream("inputs/day10.input");
 		while (getline(file, line)) {
 			jolts.push_back({ (u64) std::stoll(line), 0 });
 		}
@@ -59,7 +60,7 @@ auto main(i32 argc, char * argv[]) -> i32 {
 		else if (jolts[i + 1].jolt - jolts[i].jolt == 3) ++dif3;
 	}
 
-	std::cout << (dif1 * dif3) << std::endl;
+	print((dif1 * dif3));
 
 	for (auto i = i32(0); i < jolts.size() - 1; ++i) {
 		for (auto j = i + 1; j < jolts.size(); ++j) {
@@ -70,7 +71,5 @@ auto main(i32 argc, char * argv[]) -> i32 {
 			}
 		}
 	}
-	std::cout << jolts[jolts.size() - 1].count << std::endl;
-
-	return 0;
+	print(jolts[jolts.size() - 1].count);
 }
diff --git a/2020/day11.cpp b/2020/days/day11.cpp
similarity index 94%
rename from 2020/day11.cpp
rename to 2020/days/day11.cpp
index c5aaa78..ecbd826 100644
--- a/2020/day11.cpp
+++ b/2020/days/day11.cpp
@@ -30,7 +30,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 template <typename Lambda>
 auto iterate_seats(const auto & seats, Lambda callback) {
@@ -62,12 +63,12 @@ auto count_seats(const auto & seats) -> usize {
 	return occupied;
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day11() -> void {
 	auto bit = u8(0b1);
 	auto seats = std::array<std::vector<std::string>, 2>();
 	{
 		auto line = std::string();
-		auto file = std::ifstream("day11.input");
+		auto file = std::ifstream("inputs/day11.input");
 		while (getline(file, line)) {
 			seats[bit].push_back(line);
 		}
@@ -94,7 +95,7 @@ auto main(i32 argc, char * argv[]) -> i32 {
 	}
 	while (!seats_equal(seats));
 
-	std::cout << count_seats(seats[0]) << std::endl;
+	print(count_seats(seats[0]));
 
 	iterate_seats(seats[0], [&seats](i32 i, i32 j) {
 		seats[0][i][j] = seats[1][i][j] = 'L';
@@ -129,7 +130,5 @@ auto main(i32 argc, char * argv[]) -> i32 {
 		});
 	} while (!seats_equal(seats));
 
-	std::cout << count_seats(seats[0]) << std::endl;
-
-	return 0;
+	print(count_seats(seats[0]));
 }
diff --git a/2020/day2.cpp b/2020/days/day2.cpp
similarity index 91%
rename from 2020/day2.cpp
rename to 2020/days/day2.cpp
index cec8af6..fa57af9 100644
--- a/2020/day2.cpp
+++ b/2020/days/day2.cpp
@@ -29,7 +29,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 struct Password {
 	u32 min;
@@ -72,11 +73,11 @@ auto count_valid_toboggan(const std::vector<Password> & passwords) -> u32 {
 	return valid;
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day2() -> void {
 	auto passwords = std::vector<Password>();
 	{
 		auto line = std::string();
-		auto file = std::ifstream("day2.input");
+		auto file = std::ifstream("inputs/day2.input");
 		while (getline(file, line)) {
 			auto index = usize(0);
 			auto password = Password{};
@@ -88,8 +89,6 @@ auto main(i32 argc, char * argv[]) -> i32 {
 		}
 	}
 
-	std::cout << count_valid_sled(passwords)     << std::endl;
-	std::cout << count_valid_toboggan(passwords) << std::endl;
-
-	return 0;
+	print(count_valid_sled(passwords)    );
+	print(count_valid_toboggan(passwords));
 }
diff --git a/2020/day3.cpp b/2020/days/day3.cpp
similarity index 60%
rename from 2020/day3.cpp
rename to 2020/days/day3.cpp
index 4c6268b..647d627 100644
--- a/2020/day3.cpp
+++ b/2020/days/day3.cpp
@@ -29,40 +29,53 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
-auto read_field_and_count_trees(std::vector<std::string> & trees, usize horizontal_increment, usize vertical_increment) -> u64 {
-	auto tree_count = u64(0);
+struct TreeVector{ usize horz;    usize vert;    };
+struct Coordinate{ usize x_index; usize y_index; };
 
-	auto x_index = usize(-horizontal_increment);
-	auto y_index = usize(-1);
-	auto line = std::string();
-	auto file = std::ifstream("day3.input");
-
-	while (getline(file, line)) {
-		auto vertical_check = (++y_index % vertical_increment == 0);
-		tree_count += vertical_check * (line[(x_index += (vertical_check * horizontal_increment)) % line.size()] == '#');
+auto read_field_and_count_trees(const std::vector<TreeVector> & vectors) -> std::vector<u64> {
+	auto tree_counts = std::vector<u64>(vectors.size());
+	auto coords      = std::vector<Coordinate>(vectors.size());
+	for (auto i = usize(0); i < coords.size(); ++i) {
+		coords[i] = { usize(-vectors[i].horz), usize(-1) };
 	}
 
-	return tree_count;
+	auto line = std::string();
+	auto file = std::ifstream("inputs/day3.input");
+
+	while (getline(file, line)) {
+		for (auto i = usize(0); i < vectors.size(); ++i) {
+			auto & vector = vectors[i];
+			auto & coord  = coords[i];
+			
+			auto vertical_check = (++coord.y_index % vector.vert == 0);
+			tree_counts[i] += vertical_check * (line[(coord.x_index += (vertical_check * vector.horz)) % line.size()] == '#');
+		}
+	}
+
+	return std::move(tree_counts);
 }
 
-auto main(i32 argc, char ** argv) -> i32 {
+auto day3() -> void {
 	auto trees       = std::vector<std::string>();
-	auto tree_counts = std::vector<u64>();
+	auto tree_counts = read_field_and_count_trees(
+		std::vector<TreeVector>{
+			{ 3, 1 },
+			{ 1, 1 },
+			{ 5, 1 },
+			{ 7, 1 },
+			{ 1, 2 },
+		}
+	);
 
-	tree_counts.push_back(read_field_and_count_trees(trees, 3, 1));
-	std::cout << tree_counts[0] << std::endl;
+	print(tree_counts[0]);
 
-	tree_counts.push_back(read_field_and_count_trees(trees, 1, 1));
-	tree_counts.push_back(read_field_and_count_trees(trees, 5, 1));
-	tree_counts.push_back(read_field_and_count_trees(trees, 7, 1));
-	tree_counts.push_back(read_field_and_count_trees(trees, 1, 2));
 	auto tree_count_product = u64(1);
 	for (auto tree_count : tree_counts) {
 		tree_count_product *= tree_count;
 	}
-	std::cout << tree_count_product << std::endl;
 
-	return 0;
+	print(tree_count_product);
 }
diff --git a/2020/day4.cpp b/2020/days/day4.cpp
similarity index 95%
rename from 2020/day4.cpp
rename to 2020/days/day4.cpp
index f0c5b78..1ba17f8 100644
--- a/2020/day4.cpp
+++ b/2020/days/day4.cpp
@@ -29,7 +29,8 @@
 #include <fstream>
 #include <iostream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 struct KeyValue {
 	std::string key;
@@ -46,13 +47,13 @@ auto try_num(const std::string & passport, usize index) -> bool {
 	return Min <= num && num <= Max;
 };
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day4() -> void {
 	auto valid_count1 = usize(0);
 	auto valid_count2 = usize(0);
 
 	auto passport = std::string();
 	auto line     = std::string();
-	auto file     = std::ifstream("day4.input");
+	auto file     = std::ifstream("inputs/day4.input");
 	while (getline(file, line)) {
 		if (line == "") {
 			auto elements = std::vector<KeyValue>{
@@ -108,7 +109,6 @@ auto main(i32 argc, char * argv[]) -> i32 {
 		}
 	}
 
-	std::cout << valid_count1 << ", " << valid_count2 << std::endl;
-	
-	return 0;
+	print(valid_count1);
+	print(valid_count2);
 }
diff --git a/2020/day5.cpp b/2020/days/day5.cpp
similarity index 90%
rename from 2020/day5.cpp
rename to 2020/days/day5.cpp
index 70d3d35..5a68158 100644
--- a/2020/day5.cpp
+++ b/2020/days/day5.cpp
@@ -30,12 +30,13 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day5() -> void {
 	auto seat = usize(0);
 	auto line = std::string();
-	auto file = std::ifstream("day5.input");
+	auto file = std::ifstream("inputs/day5.input");
 
 	auto seats = std::vector<usize>();
 
@@ -49,16 +50,14 @@ auto main(i32 argc, char * argv[]) -> i32 {
 		}
 		seats.push_back(local_seat);
 	}
-	std::cout << seat << std::endl;
+	print(seat);
 
 	std::sort(seats.begin(), seats.end());
 
 	for (auto i = usize(0); i < seats.size() - 1; ++i) {
 		if (seats[i] + 2 == seats[i + 1]) {
-			std::cout << (seats[i] + 1) << std::endl;
+			print((seats[i] + 1));
 			break;
 		}
 	}
-
-	return 0;
 }
diff --git a/2020/day6.cpp b/2020/days/day6.cpp
similarity index 91%
rename from 2020/day6.cpp
rename to 2020/days/day6.cpp
index ae1035b..b3a3dbe 100644
--- a/2020/day6.cpp
+++ b/2020/days/day6.cpp
@@ -29,12 +29,13 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day6() -> void {
 	{
 		auto line    = std::string();
-		auto file    = std::ifstream("day6.input");
+		auto file    = std::ifstream("inputs/day6.input");
 
 		auto answers = std::vector<u32>(26);
 
@@ -57,8 +58,7 @@ auto main(i32 argc, char * argv[]) -> i32 {
 				}
 			}
 		}
-		std::cout << sum_1 << ", " << sum_2 << std::endl;
+		print(sum_1);
+		print(sum_2);
 	}
-
-	return 0;
 }
diff --git a/2020/day7.cpp b/2020/days/day7.cpp
similarity index 93%
rename from 2020/day7.cpp
rename to 2020/days/day7.cpp
index 97991ea..8c2d8cc 100644
--- a/2020/day7.cpp
+++ b/2020/days/day7.cpp
@@ -32,7 +32,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 struct SubBag { std::string type; u32 count; };
 
@@ -60,11 +61,11 @@ auto count_to(const std::string & search, std::map<std::string, Edges> & map) ->
 	return counted;
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day7() -> void {
 	auto bag_graph = std::map<std::string, Edges>();
 	{
 		auto line = std::string();
-		auto file = std::ifstream("day7.input");
+		auto file = std::ifstream("inputs/day7.input");
 		while (getline(file, line)) {
 			auto find = line.find("bag") - 1;
 			auto bag_type = line.substr(0, line.find("bag") - 1);
@@ -96,9 +97,7 @@ auto main(i32 argc, char * argv[]) -> i32 {
 			}
 		}
 	}
-	std::cout << seen.size() << std::endl;
+	print(seen.size());
 
-	std::cout << (count_to("shiny gold", bag_graph) - 1) << std::endl;
-
-	return 0;
+	print((count_to("shiny gold", bag_graph) - 1));
 }
diff --git a/2020/day8.cpp b/2020/days/day8.cpp
similarity index 94%
rename from 2020/day8.cpp
rename to 2020/days/day8.cpp
index 030bceb..0d770cd 100644
--- a/2020/day8.cpp
+++ b/2020/days/day8.cpp
@@ -29,7 +29,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 enum OpCode { Acc, Jmp, Nop };
 struct Op{ OpCode code; i32 num; bool executed; };
@@ -81,11 +82,11 @@ auto attempt_swap(State & state, std::vector<Op> & ops) -> bool {
 	return false;
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day8() -> void {
 	auto ops = std::vector<Op>();
 	{
 		auto line = std::string();
-		auto file = std::ifstream("day8.input");
+		auto file = std::ifstream("inputs/day8.input");
 		while (getline(file, line)) {
 			ops.push_back(extract_op(line));
 		}
@@ -95,18 +96,16 @@ auto main(i32 argc, char * argv[]) -> i32 {
 	while (!ops[state.isp].executed) {
 		execute(state, ops);
 	}
-	std::cout << state.acc << std::endl;
+	print(state.acc);
 
 	for (auto & op : ops) { op.executed = false; }
 
 	state = State{ 0, 0 };
 	for (;;) {
 		if (attempt_swap(state, ops)) {
-			std::cout << state.acc << std::endl;
+			print(state.acc);
 			break;
 		}
 		execute(state, ops);
 	}
-
-	return 0;
 }
diff --git a/2020/day9.cpp b/2020/days/day9.cpp
similarity index 92%
rename from 2020/day9.cpp
rename to 2020/days/day9.cpp
index 1668fd5..987fc9c 100644
--- a/2020/day9.cpp
+++ b/2020/days/day9.cpp
@@ -29,7 +29,8 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
 auto find_sum(usize index, std::vector<u64> xmas) {
 	for (auto i = index - 25; i < index - 1; ++i) {
@@ -42,10 +43,10 @@ auto find_sum(usize index, std::vector<u64> xmas) {
 	return false;
 }
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto day9() -> void {
 	auto xmas = std::vector<u64>();
 	auto line = std::string();
-	auto file = std::ifstream("day9.input");
+	auto file = std::ifstream("inputs/day9.input");
 	while (getline(file, line)) {
 		xmas.push_back(std::stoll(line));
 	}
@@ -53,7 +54,7 @@ auto main(i32 argc, char * argv[]) -> i32 {
 	auto invalid = u64(0);
 	for (auto i = usize(25); i < xmas.size(); ++i) {
 		if (!find_sum(i, xmas)) {
-			std::cout << (invalid = xmas[i]) << std::endl;
+			print((invalid = xmas[i]));
 			break;
 		}
 	}
@@ -82,7 +83,5 @@ auto main(i32 argc, char * argv[]) -> i32 {
 			max = xmas[i];
 		}
 	}
-	std::cout << (min + max) << std::endl;
-
-	return 0;
+	print((min + max));
 }
diff --git a/2020/day1.input b/2020/inputs/day1.input
similarity index 100%
rename from 2020/day1.input
rename to 2020/inputs/day1.input
diff --git a/2020/day10.input b/2020/inputs/day10.input
similarity index 100%
rename from 2020/day10.input
rename to 2020/inputs/day10.input
diff --git a/2020/day11.input b/2020/inputs/day11.input
similarity index 100%
rename from 2020/day11.input
rename to 2020/inputs/day11.input
diff --git a/2020/day2.input b/2020/inputs/day2.input
similarity index 100%
rename from 2020/day2.input
rename to 2020/inputs/day2.input
diff --git a/2020/day3.input b/2020/inputs/day3.input
similarity index 100%
rename from 2020/day3.input
rename to 2020/inputs/day3.input
diff --git a/2020/day4.input b/2020/inputs/day4.input
similarity index 100%
rename from 2020/day4.input
rename to 2020/inputs/day4.input
diff --git a/2020/day5.input b/2020/inputs/day5.input
similarity index 100%
rename from 2020/day5.input
rename to 2020/inputs/day5.input
diff --git a/2020/day6.input b/2020/inputs/day6.input
similarity index 100%
rename from 2020/day6.input
rename to 2020/inputs/day6.input
diff --git a/2020/day7.input b/2020/inputs/day7.input
similarity index 100%
rename from 2020/day7.input
rename to 2020/inputs/day7.input
diff --git a/2020/day8.input b/2020/inputs/day8.input
similarity index 100%
rename from 2020/day8.input
rename to 2020/inputs/day8.input
diff --git a/2020/day9.input b/2020/inputs/day9.input
similarity index 100%
rename from 2020/day9.input
rename to 2020/inputs/day9.input
diff --git a/2020/template.cpp b/2020/misc/day.cpp.template
similarity index 91%
rename from 2020/template.cpp
rename to 2020/misc/day.cpp.template
index 51a940b..52dfe9d 100644
--- a/2020/template.cpp
+++ b/2020/misc/day.cpp.template
@@ -29,16 +29,15 @@
 #include <iostream>
 #include <fstream>
 
-#include "types.hpp"
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
 
-auto main(i32 argc, char * argv[]) -> i32 {
+auto current_day() -> void {
 	{
 		auto line = std::string();
-		auto file = std::ifstream("dayNUM.input");
+		auto file = std::ifstream("inputs/current_day.input");
 		while (getline(file, line)) {
 			
 		}
 	}
-
-	return 0;
 }
diff --git a/2020/misc/main.cpp b/2020/misc/main.cpp
new file mode 100644
index 0000000..c4752db
--- /dev/null
+++ b/2020/misc/main.cpp
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include "types.hpp"
+
+extern auto current_day() -> void;
+
+auto main(i32 argc, char * argv[]) -> i32 {
+	current_day();
+
+	return 0;
+}
+
diff --git a/2020/misc/main_test.cpp b/2020/misc/main_test.cpp
new file mode 100644
index 0000000..0d8954d
--- /dev/null
+++ b/2020/misc/main_test.cpp
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <iostream>
+#include <string>
+#include <chrono>
+
+#include "types.hpp"
+
+extern auto current_day() -> void;
+
+auto main(i32 argc, char * argv[]) -> i32 {
+	auto TEST_CYCLES = 1;
+	if (argc >= 2) {
+		TEST_CYCLES = std::stoi(argv[1]);
+	}
+
+	std::cout << "Starting test with " << TEST_CYCLES << " iterations..." << std::endl;
+	auto begin1 = std::chrono::high_resolution_clock::now();
+
+	for (auto i = usize(0); i < TEST_CYCLES; ++i) {
+		current_day();
+	}
+
+	auto end1 = std::chrono::high_resolution_clock::now();
+
+	if (argc >= 3) {
+		if (argv[2] == std::string("millis")) {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(end1 - begin1).count() << " milliseconds"<< std::endl;
+		} else if (argv[2] == std::string("nanos")) {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::nanoseconds>(end1 - begin1).count() << " nanoseconds"<< std::endl;
+		} else if (argv[2] == std::string("micros")) {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::microseconds>(end1 - begin1).count() << " microsenconds"<< std::endl;
+		} else {
+			std::cout << "Unkown time scale '" << argv[2] << "'" << std::endl;
+		}
+	} else {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::microseconds>(end1 - begin1).count() << " microseconds"<< std::endl;
+	}
+
+	return 0;
+}
+
diff --git a/2020/misc/print.hpp b/2020/misc/print.hpp
new file mode 100644
index 0000000..5960cd8
--- /dev/null
+++ b/2020/misc/print.hpp
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#ifndef TEST_BUILD
+#define print(x) std::cout << (x) << std::endl
+#else
+#define print(x)
+#endif
diff --git a/2020/types.cpp b/2020/misc/types.cpp
similarity index 100%
rename from 2020/types.cpp
rename to 2020/misc/types.cpp
diff --git a/2020/types.hpp b/2020/misc/types.hpp
similarity index 100%
rename from 2020/types.hpp
rename to 2020/misc/types.hpp

From 0f6b89142363a3c5d20717b9b529b741a482bd6e Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Fri, 11 Dec 2020 09:29:57 -0800
Subject: [PATCH 02/12] Updated make clean rule

---
 2020/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/2020/Makefile b/2020/Makefile
index 812ac33..3860638 100644
--- a/2020/Makefile
+++ b/2020/Makefile
@@ -14,4 +14,4 @@ out/types.o: misc/types.hpp misc/types.cpp
 
 .PHONY: clean
 clean:
-	rm out/* day*.out day*.output
+	rm -f out/* day*.out day*.output

From 0701aec56941b45dd5dff9fe8599e8e03588015e Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Fri, 11 Dec 2020 21:33:26 -0800
Subject: [PATCH 03/12] Completed day 12

---
 2020/days/day12.cpp     | 104 ++++++
 2020/inputs/day12.input | 748 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 852 insertions(+)
 create mode 100644 2020/days/day12.cpp
 create mode 100644 2020/inputs/day12.input

diff --git a/2020/days/day12.cpp b/2020/days/day12.cpp
new file mode 100644
index 0000000..cc0ee01
--- /dev/null
+++ b/2020/days/day12.cpp
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+struct Instruction{ char op; i32 num; };
+
+auto day12() -> void {
+	auto instructions = std::vector<Instruction>();
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day12.input");
+		while (getline(file, line)) {
+			instructions.push_back({ line[0], std::stoi(line.substr(1, line.size() - 1)) });
+			if (line[0] == 'L' || line[0] == 'R') {
+				instructions[instructions.size() - 1].num /= 90;
+			}
+		}
+	}
+
+	{
+		auto ship_x = i32(0);
+		auto ship_y = i32(0);
+		auto direction = i32(2);
+		for (const auto & instruction : instructions) {
+			switch (instruction.op) {
+				case 'N': ship_y += instruction.num; break;
+				case 'E': ship_x += instruction.num; break;
+				case 'S': ship_y -= instruction.num; break;
+				case 'W': ship_x -= instruction.num; break;
+				case 'R': direction = (direction - instruction.num + 4) % 4; break;
+				case 'L': direction = (direction + instruction.num    ) % 4; break;
+				case 'F':
+					ship_x += ((direction - 1) % 2) * instruction.num;
+					ship_y += ((direction - 2) % 2) * instruction.num;
+					break;
+			}
+		}
+		print((std::abs(ship_x) + std::abs(ship_y)));
+	}
+
+	{
+		auto ship_x = i32(0);
+		auto ship_y = i32(0);
+		auto waypoint_x = i32(10);
+		auto waypoint_y = i32( 1);
+		for (const auto & instruction : instructions) {
+			switch (instruction.op) {
+				case 'N': waypoint_y += instruction.num; break;
+				case 'E': waypoint_x += instruction.num; break;
+				case 'S': waypoint_y -= instruction.num; break;
+				case 'W': waypoint_x -= instruction.num; break;
+				case 'R':
+					for (auto i = i32(0); i < instruction.num; ++i) {
+						auto copy = waypoint_x;
+						waypoint_x =  waypoint_y;
+						waypoint_y = -copy;
+					}
+					break;
+				case 'L':
+					for (auto i = i32(0); i < instruction.num; ++i) {
+						auto copy = waypoint_x;
+						waypoint_x = -waypoint_y;
+						waypoint_y =  copy;
+					}
+					break;
+				case 'F':
+					ship_x += waypoint_x * instruction.num;
+					ship_y += waypoint_y * instruction.num;
+					break;
+			}
+		}
+		print((std::abs(ship_x) + std::abs(ship_y)));
+	}
+}
diff --git a/2020/inputs/day12.input b/2020/inputs/day12.input
new file mode 100644
index 0000000..31d6bc8
--- /dev/null
+++ b/2020/inputs/day12.input
@@ -0,0 +1,748 @@
+W5
+R90
+W3
+F98
+F87
+R90
+F57
+R180
+F3
+L90
+F60
+N3
+F94
+N3
+E2
+S2
+W2
+L90
+F26
+R90
+W1
+F58
+S5
+F22
+N3
+F95
+N1
+W1
+F11
+R180
+S3
+R270
+N1
+N1
+E4
+S3
+F81
+W2
+S2
+L90
+S4
+R90
+S1
+E1
+L90
+S4
+E2
+F72
+S1
+W1
+F73
+W4
+L180
+S1
+W5
+S5
+R90
+E3
+N3
+F28
+N1
+F84
+R90
+E5
+F13
+W5
+L90
+F11
+E4
+F63
+S1
+S2
+L90
+N3
+S5
+F20
+W1
+S4
+W1
+S2
+F67
+N1
+R180
+F11
+E1
+R90
+S2
+R90
+F38
+S5
+F27
+S5
+W3
+S3
+L90
+N2
+W2
+S1
+N4
+R90
+E1
+F16
+L90
+E4
+N1
+L90
+F89
+E5
+F90
+E1
+L180
+N1
+E3
+S2
+F58
+S3
+F53
+R90
+F100
+W1
+F53
+W5
+L90
+W3
+N4
+F54
+R180
+S2
+E2
+F63
+L90
+S4
+F40
+F90
+N3
+F83
+E5
+F35
+W4
+W5
+S3
+E2
+S2
+S1
+F12
+L90
+S1
+F41
+R90
+S3
+R90
+F66
+S2
+F34
+N5
+R90
+E5
+R90
+F25
+N5
+R90
+W1
+S2
+S2
+R90
+E3
+R90
+F95
+N3
+W2
+S4
+R90
+E3
+L90
+E3
+R90
+N2
+F84
+L90
+N2
+R90
+S1
+L90
+F93
+L90
+F60
+S4
+F85
+S2
+F84
+R180
+W5
+N4
+W5
+R270
+S2
+E2
+L180
+W4
+R180
+W5
+F56
+E1
+F45
+W4
+R90
+L180
+S1
+W4
+S5
+F87
+R180
+S2
+F76
+R90
+F76
+S1
+E4
+F6
+S1
+E2
+F47
+S3
+W2
+F16
+F75
+E3
+F75
+E4
+R90
+N5
+W3
+F1
+S1
+F8
+E2
+F64
+R90
+W4
+S5
+R90
+N5
+R90
+E2
+N1
+E1
+L180
+F31
+L180
+E5
+L90
+N3
+R90
+F77
+E3
+F65
+E4
+R90
+W1
+N3
+E3
+F4
+R90
+E3
+N4
+F28
+R180
+N2
+L90
+S2
+L90
+N1
+W1
+L180
+E4
+F51
+W4
+F9
+S4
+R90
+W5
+S4
+R90
+E3
+W2
+F44
+R90
+E1
+L180
+S4
+F93
+S2
+F58
+R90
+F80
+L90
+E2
+F20
+R90
+F19
+S4
+F22
+W1
+S2
+F62
+N2
+E5
+F21
+L90
+F16
+W2
+F58
+E2
+F54
+N1
+F83
+N3
+E2
+F62
+S3
+L90
+E3
+L270
+F29
+N5
+L90
+S2
+F19
+E5
+R180
+F87
+R180
+S2
+F22
+W3
+S5
+F35
+E3
+N5
+R180
+E2
+R270
+N3
+F5
+L90
+W3
+S1
+L90
+S2
+R270
+N5
+L180
+F79
+N3
+F82
+N3
+F73
+N4
+F57
+L90
+W3
+F26
+N4
+E5
+N4
+F48
+R90
+F62
+R90
+F36
+E1
+F76
+R90
+N3
+F83
+E5
+L90
+S1
+F1
+E1
+L90
+F67
+W3
+L90
+F42
+E4
+S2
+L180
+F89
+N1
+E4
+S4
+W1
+S2
+L90
+F91
+R90
+F78
+N5
+F29
+W2
+R90
+W1
+R90
+E2
+F40
+E2
+F76
+R90
+E4
+L90
+W3
+S1
+W3
+N4
+F81
+W4
+F22
+N1
+W1
+F47
+E3
+R90
+N5
+W4
+L90
+F44
+L90
+F58
+S1
+R90
+E3
+F91
+N1
+W4
+N5
+L90
+F60
+F8
+S4
+F17
+E5
+N2
+L90
+F37
+L180
+W4
+L180
+W4
+F93
+S5
+F71
+R90
+N5
+E3
+F20
+R90
+N5
+E5
+R90
+S2
+R180
+S5
+L90
+F26
+E4
+F49
+E5
+S4
+E4
+N1
+L180
+F33
+E1
+L90
+S4
+E5
+N5
+L180
+F60
+S1
+F53
+W1
+F34
+E2
+N3
+E2
+S5
+F61
+F32
+F18
+L90
+W4
+N4
+R90
+E4
+L90
+F26
+S3
+W4
+S5
+E5
+S2
+R90
+S5
+R90
+E2
+R90
+N2
+S3
+L90
+S3
+S2
+L90
+E5
+F31
+R180
+E2
+F42
+R90
+W4
+L90
+E5
+S3
+F79
+R90
+F76
+W1
+F9
+N1
+F91
+R90
+N3
+F32
+L180
+N4
+W2
+F18
+N5
+L90
+S4
+L180
+F22
+E4
+R180
+S2
+L90
+W5
+F31
+L180
+E1
+F15
+W1
+S5
+E4
+F56
+L90
+F7
+S3
+E4
+F13
+R90
+S4
+F78
+R180
+E3
+N1
+R90
+W4
+F29
+S4
+L90
+S4
+W4
+L180
+F6
+F84
+E4
+L90
+F29
+E2
+F75
+E3
+N4
+F33
+L270
+S4
+F62
+E2
+N4
+F50
+E1
+E2
+L270
+F100
+R180
+S2
+F89
+N2
+W3
+F5
+E5
+N2
+F75
+S3
+F2
+S4
+W3
+F33
+S5
+R90
+E5
+F20
+S1
+L90
+S4
+F10
+W5
+S2
+L90
+E3
+E1
+S3
+F41
+E5
+L90
+F28
+S2
+F40
+S2
+S4
+N1
+F15
+W5
+W2
+R270
+E5
+R90
+E4
+F50
+R90
+S4
+E1
+N4
+F73
+L90
+W2
+L270
+E4
+S1
+F30
+S3
+W4
+L180
+W4
+F6
+R90
+F43
+N5
+W3
+W3
+R90
+S2
+R90
+F50
+W2
+S4
+L90
+L180
+W1
+L270
+E3
+N2
+E2
+F48
+W1
+L90
+N4
+L90
+E3
+F86
+L180
+F10
+S1
+F36
+S4
+F33
+N5
+L90
+F14
+S2
+E4
+N4
+R90
+S2
+W2
+N2
+L180
+N4
+R90
+L90
+E5
+S1
+F82
+W1
+S1
+F19
+E3
+F19
+S2
+W1
+F18
+L90
+F43
+W1
+N2
+E3
+L90
+S1
+F75
+L90
+E4
+F80
+N5
+F15
+F53
+N4
+E5
+L90
+E1
+W5
+R270
+F17
+F63
+W2
+F20
+E1
+S3
+F19
+E1
+F99
+S1
+W1
+F23
+L180
+S3
+W4
+F76

From 16fbe23142083a083291c27d9c0f3fa452884a83 Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Sun, 13 Dec 2020 23:08:32 -0800
Subject: [PATCH 04/12] Completed day 13 p1 and day 14

---
 2020/days/day13.cpp     | 106 ++++++++
 2020/days/day14.cpp     | 112 ++++++++
 2020/inputs/day13.input |   3 +
 2020/inputs/day14.input | 556 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 777 insertions(+)
 create mode 100644 2020/days/day13.cpp
 create mode 100644 2020/days/day14.cpp
 create mode 100644 2020/inputs/day13.input
 create mode 100644 2020/inputs/day14.input

diff --git a/2020/days/day13.cpp b/2020/days/day13.cpp
new file mode 100644
index 0000000..576af53
--- /dev/null
+++ b/2020/days/day13.cpp
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+struct Pair{ u64 id; usize index; };
+
+auto find_least(u64 new_base, u64 new_loop, u64 req_base, u64 req_loop, u64 iter) -> u64 {
+	while ((new_base + ++iter * new_loop - req_base) % req_loop != 0);
+	return new_base + iter * new_loop;
+}
+
+auto day13() -> void {
+	auto ready = usize(0);
+	auto buses = std::vector<Pair>();
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day13.input");
+		getline(file, line);
+		ready = std::stoi(line);
+		getline(file, line);
+		auto start = usize(0);
+		auto end   = usize(0);
+		auto index = usize(0);
+		auto id    = std::string();
+		while ((end = line.find(',', start)) != std::string::npos) {
+			id = line.substr(start, end - start);
+			if (id != "x") {
+				buses.push_back({ u64(std::stoi(line.substr(start, end - start))), index });
+			}
+			start = end + 1;
+			++index;
+		}
+		end = line.size();
+		id = line.substr(start, end - start);
+		if (id != "x") {
+			buses.push_back({ u64(std::stoi(line.substr(start, end - start))), index });
+		}
+	}
+	
+	auto id      = buses[0].id;
+	auto minutes = buses[0].id - (ready % buses[0].id);
+	for (auto i = usize(1); i < buses.size(); ++i) {
+		auto local_minutes = buses[i].id - (ready % buses[i].id);
+		if (local_minutes < minutes) {
+			id      = buses[i].id;
+			minutes = local_minutes;
+		}
+	}
+	print((id * minutes));
+
+	auto req_base = usize(0);
+	auto req_loop = usize(1);
+	for (auto i = usize(1); i < buses.size(); ++i) {
+		auto base_loop = usize(-1);
+		while ((++base_loop * buses[0].id + buses[i].index) % buses[i].id != 0);
+
+		auto rep_loop = usize(0);
+		while ((++rep_loop * buses[0].id) % buses[i].id != 0);
+
+		req_base = find_least(base_loop, rep_loop, req_base, req_loop, -1);
+		if (i < buses.size() - 1) {
+			req_loop = find_least(0, rep_loop, 0, req_loop, 0);
+		}
+		/*
+		required_base (rqb), required_loop (rql)
+
+		base_loop (bl), repeat_loop (rl)
+
+		rqb + a0 * rql = bl + a1 * rl < minimize and store in required loop
+		a0 = (bl + a1 * rl - rqb) / rql
+
+		b0 * rql = b1 * rl < minimize and store in required loop
+		*/
+	}
+	print((req_base * buses[0].id));
+}
diff --git a/2020/days/day14.cpp b/2020/days/day14.cpp
new file mode 100644
index 0000000..a38fbd6
--- /dev/null
+++ b/2020/days/day14.cpp
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <map>
+#include <string>
+#include <bitset>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+struct Op{ u8 op; u64 num1; u64 num2; };
+
+auto set_memory(std::map<u64, u64> & map, u64 addr, const std::vector<bool> & maskX, usize index, u64 value) -> void {
+	while (++index < maskX.size() && !maskX[index]);
+	if (index == maskX.size()) {
+		map.insert_or_assign(addr, value);
+	} else {
+		set_memory(map, addr, maskX, index, value);
+		set_memory(map, addr ^ (u64(1) << (maskX.size() - index - 1)), maskX, index, value);
+	}
+}
+
+auto day14() -> void {
+	auto ops = std::vector<Op>();
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day14.input");
+		while (getline(file, line)) {
+			if (line.find("mask") != std::string::npos) {
+				auto mask0 = u64(-1);
+				auto mask1 = u64( 0);
+				for (auto i = usize(7); i < line.size(); ++i) {
+					if (line[i] == '0') {
+						mask0 ^= (u64(1) << (42 - i));
+					} else if (line[i] == '1') {
+						mask1 ^= (u64(1) << (42 - i));
+					}
+				}
+				ops.push_back({ 0, mask0, mask1 });
+			} else {
+				auto value = line.find("=") + 2;
+				ops.push_back({
+					1,
+					u64(std::stoll(line.substr(4, line.find("]") - 4))),
+					u64(std::stoll(line.substr(value, line.size() - value)))
+				});
+			}
+		}
+	}
+	auto mask0  = u64(-1);
+	auto mask1  = u64( 0);
+	auto memory = std::map<u64, u64>();
+	for (auto op : ops) {
+		if (op.op == 0) {
+			mask0 = op.num1;
+			mask1 = op.num2;
+		} else {
+			memory.insert_or_assign(op.num1, (op.num2 & mask0) | mask1);
+		}
+	}
+	auto sum = u64(0);
+	for(auto mem : memory) {
+		sum += mem.second;
+	}
+	print(sum);
+
+	mask1  = u64(0);
+	memory = std::map<u64, u64>();
+	auto maskX = std::vector<bool>(36);
+	for (auto op : ops) {
+		if (op.op == 0) {
+			mask1 = op.num2;
+			for (auto i = usize(0); i < maskX.size(); ++i) {
+				auto bit = u64(1) << u64(35 - i);
+				maskX[i] = (op.num1 & bit) && !(op.num2 & bit);
+			}
+		} else {
+			set_memory(memory, op.num1 | mask1, maskX, -1, op.num2);
+		}
+	}
+	sum = u64(0);
+	for(auto mem : memory) {
+		sum += mem.second;
+	}
+	print(sum);
+}
diff --git a/2020/inputs/day13.input b/2020/inputs/day13.input
new file mode 100644
index 0000000..20bcf07
--- /dev/null
+++ b/2020/inputs/day13.input
@@ -0,0 +1,3 @@
+1001171
+17,x,x,x,x,x,x,41,x,x,x,37,x,x,x,x,x,367,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,19,x,x,x,23,x,x,x,x,x,29,x,613,x,x,x,x,x,x,x,x,x,x,x,x,13
+
diff --git a/2020/inputs/day14.input b/2020/inputs/day14.input
new file mode 100644
index 0000000..fa02b57
--- /dev/null
+++ b/2020/inputs/day14.input
@@ -0,0 +1,556 @@
+mask = 00X1011010111X01X1X010X01X1111X11100
+mem[13879] = 56974
+mem[26072] = 842
+mem[47322] = 62104110
+mem[31450] = 372784
+mem[54364] = 2818920
+mask = 01000X10101XX0011000X00XXX00101X0101
+mem[13358] = 73976240
+mem[41121] = 3647124
+mask = 010000X01111X0011000X01010X1001100X0
+mem[49893] = 63539
+mem[63669] = 79316429
+mem[19136] = 256
+mem[1117] = 1244
+mem[56655] = 267815
+mem[22811] = 142
+mask = 0101011010111X0111X010110000XXX1010X
+mem[40297] = 21028792
+mem[16007] = 950419537
+mem[40907] = 2010
+mem[27377] = 525
+mem[0] = 209
+mem[41317] = 2312973
+mem[4641] = 1227100
+mask = X0X000101X111001110X011X1X1010X10100
+mem[24322] = 103589922
+mem[2572] = 1231
+mem[53327] = 814998856
+mem[30460] = 25015
+mask = 00000010XX101X11X0110100X0X001X010X1
+mem[50914] = 37339
+mem[50218] = 5021282
+mask = 0X0X00X01XX0110X1101X0X010000110X101
+mem[3780] = 51750101
+mem[8561] = 638
+mem[64747] = 215
+mem[51358] = 194347939
+mem[29912] = 9717
+mem[44684] = 418165
+mask = 0X0X00101011XXX11100001X0101X01101XX
+mem[1418] = 81827528
+mem[38228] = 399582
+mem[57488] = 7003
+mem[22080] = 112130
+mem[29467] = 2198074
+mem[32800] = 35048851
+mask = 010X00001011100111X0001X0100011010X1
+mem[16589] = 1922920
+mem[31011] = 88738170
+mem[35178] = 4791
+mem[17792] = 5560
+mem[50656] = 1695
+mem[22720] = 1584409
+mem[54364] = 1486
+mask = 01XX011010X110XXX1X001010X01000X1011
+mem[19230] = 13477
+mem[41397] = 781359
+mem[11599] = 7687201
+mem[2817] = 26775
+mask = X10001XX1000100X1X00001X01X100011100
+mem[288] = 1886
+mem[32911] = 326403
+mem[48084] = 66681
+mask = 00001000X011110X11011000X0X000XX10X1
+mem[41020] = 3202
+mem[21434] = 5634478
+mask = 00X0XX001011X0X1X10X100001110111X011
+mem[33545] = 1876
+mem[28976] = 581977039
+mask = 0X11011010111101011000X1101X000X1110
+mem[19071] = 770610413
+mem[20064] = 1694
+mem[43482] = 2871
+mem[46365] = 3148234
+mem[52059] = 3513
+mem[18760] = 1548
+mem[61977] = 605
+mask = 010X01XX1X11100X11001X10X10110000001
+mem[53801] = 111695
+mem[11683] = 168184
+mem[20469] = 1949
+mask = X1010110X01111011100X010000XX0000000
+mem[55872] = 2261951
+mem[13140] = 15964
+mem[45204] = 22572
+mask = X10X0000XX111X01100011X11X1100101101
+mem[56655] = 124863920
+mem[32800] = 20227
+mem[58864] = 42605725
+mem[59474] = 859
+mem[59729] = 141193
+mem[18342] = 1631
+mask = 01100XX01011100111X00010XX01X0XX010X
+mem[13572] = 3383121
+mem[32800] = 25726954
+mem[54193] = 54397
+mem[3305] = 251510
+mem[52294] = 33972
+mask = 0100X0XX10XX11X11101001010X1X110X100
+mem[3991] = 3201095
+mem[19248] = 1173
+mem[17507] = 684436
+mem[37324] = 694
+mem[11150] = 44468495
+mem[16853] = 3978967
+mem[10293] = 3552
+mask = X0X00000X01010011011011X1000X01XX001
+mem[54689] = 1224
+mem[36536] = 33407636
+mem[22811] = 296513
+mem[58491] = 109654
+mask = 010XX1111011000X1000X1000100X00011X0
+mem[20982] = 1468
+mem[15854] = 13972
+mem[55563] = 121451
+mem[28871] = 732
+mask = 00100X100001000001001101XX100X10XX10
+mem[37549] = 11144610
+mem[58939] = 280786876
+mem[38833] = 1473210
+mem[44075] = 571
+mem[21698] = 5427778
+mem[35937] = 544693
+mask = 0100011010111XX10X00011011X010110110
+mem[63719] = 36151477
+mem[43205] = 79985
+mem[9431] = 23613381
+mem[38228] = 93679
+mem[45544] = 946568
+mask = 0X000000101010011101110X11001000XX00
+mem[2730] = 8086855
+mem[50422] = 3607
+mem[9544] = 3738
+mask = 0X0XXXX010X1100111100010000001010010
+mem[17216] = 2231300
+mem[40965] = 30453
+mem[43536] = 1780
+mem[26440] = 712936
+mem[26845] = 445304638
+mask = 01X000X1X0101001101111X1000X0001X0XX
+mem[34736] = 35
+mem[23584] = 62941351
+mask = 01X000XX1110XX11XX10010000010X00X110
+mem[35014] = 2725
+mem[31317] = 3
+mask = 000XX0XX101010X1X0X111X0100001100001
+mem[372] = 21946096
+mem[10488] = 41777407
+mem[23528] = 1708407
+mem[60206] = 182569990
+mem[44075] = 816675
+mem[43028] = 618865
+mask = 0X00X000101X1X01110XX01XX0000011X001
+mem[955] = 17506
+mem[41317] = 3162029
+mem[37] = 9168685
+mem[24435] = 33494
+mem[10291] = 901681
+mem[26688] = 23163
+mask = 0100100110X111011XX10010101101101X00
+mem[53694] = 184478
+mem[38156] = 140154654
+mem[3645] = 99833620
+mem[5194] = 7438
+mem[13132] = 187583
+mem[10626] = 213169401
+mask = 0X00X11X1011000X100000XXX0001010XX11
+mem[58468] = 3932
+mem[47108] = 13422709
+mem[20791] = 25670347
+mask = 0100010010111000110000X1X11111X0X100
+mem[64332] = 58063181
+mem[20791] = 97103200
+mem[21178] = 704
+mask = 010X000010101X0X11X111001100X1X011XX
+mem[29912] = 96861
+mem[11661] = 15933204
+mem[31973] = 1597059
+mask = 010X0010001XX001110011X0000X00101110
+mem[54377] = 929
+mem[1578] = 1628469
+mem[9066] = 1039223
+mem[54819] = 131459054
+mem[59746] = 97979749
+mem[21742] = 919
+mask = 010X000010111X011110X100X00X0000X00X
+mem[25877] = 1030474
+mem[40848] = 441
+mem[19136] = 40
+mem[41305] = 509818516
+mask = 11010011XX111011110X111011X11X00X100
+mem[56916] = 23553145
+mem[43067] = 120593523
+mem[41993] = 121958
+mem[16589] = 469
+mask = 00000XX0101111011101X1011XX1001XXXX0
+mem[44363] = 1739
+mem[15915] = 49544
+mem[5729] = 173493396
+mem[29213] = 41122
+mem[50656] = 1531
+mask = 0X010X1010111X0111000X1XX10100X101XX
+mem[58111] = 1227
+mem[45142] = 3293
+mem[30952] = 2965075
+mem[25181] = 578696
+mem[50656] = 60702685
+mask = 0111011010111XX10100X100110101000X1X
+mem[59881] = 82070
+mem[60524] = 62394
+mem[35663] = 1981
+mem[27322] = 216531615
+mem[8965] = 14469
+mem[13388] = 1148662
+mem[13342] = 92607190
+mask = X1000XX110X0111XXX010010X00101110101
+mem[2228] = 40376
+mem[64755] = 1327525
+mask = 11010010X0XX10X11X0X1X011001101X110X
+mem[15280] = 2364003
+mem[19478] = 72063090
+mem[8497] = 28240
+mem[45678] = 2811
+mem[52231] = 39955
+mask = 0X001111X011000010X01011X1000XX00X11
+mem[24827] = 1639
+mem[13879] = 119218
+mem[17610] = 6101768
+mem[48448] = 3972
+mask = XX0000X0X11110X110001111011X00010101
+mem[65388] = 9968
+mem[26462] = 45065510
+mem[27496] = 70270
+mask = 01010X1X111X1001101X101X0XX000000001
+mem[10134] = 755
+mem[34940] = 3959699
+mem[26321] = 156
+mem[63789] = 36543477
+mask = X10X001010111001X1000100001XX00X101X
+mem[59095] = 888920
+mem[26072] = 189525541
+mem[41506] = 78022
+mask = 01X000101X1X10X11010X1X010X1010X011X
+mem[19618] = 43629
+mem[16853] = 176218496
+mem[27558] = 9383
+mask = 000000X01011101111001XX00000X0000110
+mem[47738] = 782
+mem[9654] = 14755
+mask = 01X0X0001X01X101110X00000000000X0101
+mem[21742] = 34626297
+mem[10621] = 1418350
+mem[45805] = 3784031
+mask = 01XX01001011101X010X001001X1010X0100
+mem[18511] = 458
+mem[4597] = 8053
+mem[34914] = 902
+mem[11895] = 2319205
+mem[54291] = 7059674
+mem[60178] = 1495
+mem[64432] = 22061
+mask = 1X110010001110011X0X01100X1XX0X01XX0
+mem[9055] = 462699
+mem[35882] = 554265333
+mem[50939] = 52443722
+mem[20552] = 160408413
+mask = 0100010010111001X100000X01X1001001X1
+mem[28976] = 404
+mem[64843] = 813
+mem[57066] = 899
+mem[16179] = 3033125
+mask = X101X01X101110X1110011X0X00010X01001
+mem[63922] = 122921015
+mem[47325] = 66631
+mem[34914] = 122827
+mem[41369] = 723416
+mem[26321] = 350572
+mem[10260] = 11917171
+mem[20396] = 112670
+mask = 00X100101011100111XX010X011X0XX001XX
+mem[11150] = 875126074
+mem[28760] = 25307778
+mem[14951] = 445519
+mem[54291] = 394307
+mem[19109] = 15584261
+mem[8221] = 524
+mask = 01000XX011111001100000001101X111X101
+mem[58015] = 18497
+mem[63992] = 530980167
+mem[26915] = 14357281
+mem[42401] = 12123838
+mem[65275] = 14601815
+mask = 010X00X0100011X011010010X00XX100010X
+mem[49005] = 39006890
+mem[121] = 119847895
+mem[16179] = 737050
+mem[52215] = 11770
+mask = 010XX0001X10X101110XX10X00000X100111
+mem[40066] = 1188
+mem[27727] = 10855
+mem[47207] = 113852179
+mask = 0X10011XX01X1011110000011X11X0XX101X
+mem[27558] = 1280
+mem[18441] = 312
+mem[22675] = 2746277
+mem[54987] = 120268
+mask = 1101XX1010111X011XX01XX0110000001110
+mem[8285] = 6819893
+mem[56655] = 10287
+mem[39027] = 158
+mem[25922] = 2798
+mem[22261] = 36850389
+mem[46394] = 48894888
+mask = X1X10010X011100111001000XX100X1X1X00
+mem[24614] = 1802
+mem[13232] = 499261
+mask = 01XX0X1010111XX11100X011010100X0X101
+mem[63992] = 12600674
+mem[56655] = 99142656
+mem[9273] = 302251593
+mask = XX000XXX1011101111XX0010000100111X00
+mem[18088] = 20379649
+mem[47508] = 111520085
+mem[38545] = 90881967
+mem[21514] = 16333
+mem[35731] = 816238944
+mask = 110111101X11X1011010X10010000111101X
+mem[13890] = 4842901
+mem[23610] = 19829
+mem[21900] = 31928769
+mem[10595] = 228191
+mem[13375] = 24467
+mem[45544] = 149815
+mask = 010XX1X0101X100X110X1111010X1100X10X
+mem[13358] = 7851
+mem[18277] = 1322
+mem[24517] = 6165
+mem[19856] = 93677767
+mask = 010X0110101XX0011100X000X00000100111
+mem[60820] = 549270
+mem[42355] = 609632
+mem[35546] = 241510
+mem[59340] = 57067
+mask = 010X00X0X0101X001X01111011X00XX01010
+mem[58491] = 456443643
+mem[49058] = 86242
+mem[24702] = 25105
+mem[35001] = 88082598
+mem[36988] = 23981732
+mem[54815] = 19064841
+mem[52231] = 329
+mask = 0XX0001X11101XX011X1X1000000110111X1
+mem[7504] = 475530227
+mem[29138] = 11235
+mem[56376] = 76699622
+mask = 0011XXX01011100X1110X111011XX1110X00
+mem[52184] = 60066
+mem[64705] = 2343316
+mem[43172] = 28305258
+mem[5362] = 2133
+mem[38763] = 2754100
+mem[52032] = 7390
+mem[2572] = 19579691
+mask = 010XX00010101001101X111X000101110011
+mem[29623] = 24098
+mem[8946] = 24951998
+mem[11382] = 184167
+mem[47522] = 6393093
+mask = XX01001010X11X011110X000XX000100X0X1
+mem[10260] = 661
+mem[25012] = 11390
+mask = 0100001010001101110101100XX110X01XX1
+mem[9055] = 297216
+mem[49887] = 26800
+mem[18511] = 3731
+mem[26845] = 42990
+mask = 00X0X00010101X1X1001100011X001100001
+mem[19591] = 197388201
+mem[51460] = 1032
+mem[9600] = 934060
+mem[58791] = 1646732
+mem[50283] = 1235563
+mem[26455] = 5018620
+mem[288] = 481559
+mask = 010X001010110X0X1X001111000XX010011X
+mem[13491] = 1626583
+mem[36536] = 239
+mem[56224] = 9125
+mem[28105] = 22015873
+mem[44531] = 8125
+mem[18760] = 25964
+mask = X101000011111X011110100011000X010X0X
+mem[58864] = 709865577
+mem[32976] = 303129
+mem[44109] = 8025520
+mem[51706] = 3030478
+mask = 00X01X0010101X0X1X011X110000X10101X1
+mem[53349] = 146801393
+mem[372] = 27164788
+mask = 0X00000010101X011XX11110X000XX1X0001
+mem[27091] = 1227
+mem[3194] = 234
+mem[37] = 4066397
+mem[43559] = 17240
+mem[36904] = 23282
+mem[9186] = 622901569
+mem[58468] = 208767
+mask = 00XX00X010X11101X101111001110100101X
+mem[9251] = 230
+mem[61367] = 78432672
+mem[37478] = 2594
+mem[64797] = 71052818
+mem[30018] = 11711518
+mem[20324] = 64836
+mem[61185] = 1433
+mask = 010000X0101X11001101011001100XXX0010
+mem[31581] = 232228
+mem[51766] = 13503
+mem[46129] = 1071
+mem[27845] = 3969749
+mem[17643] = 282089
+mem[60524] = 10654
+mask = 010X00X01X1110011XX01010XX00X0X10101
+mem[41317] = 20899132
+mem[17792] = 1949
+mem[1117] = 4931
+mem[21452] = 423952
+mem[29912] = 36667871
+mem[10260] = 15401611
+mem[28642] = 2840753
+mask = 000000X0101111011101XXXX000X001X01X1
+mem[57488] = 297477423
+mem[8228] = 240002
+mem[45051] = 1209316
+mem[65123] = 1339
+mask = 0100000010101X001111X1011X0001X0X00X
+mem[25750] = 10538421
+mem[59160] = 13024648
+mem[7581] = 521295867
+mem[44127] = 10349
+mem[20791] = 263486916
+mem[58844] = 37364
+mem[44165] = 213775351
+mask = 010X0X0010XX10011100001X0X0X1X0001X1
+mem[20221] = 7207
+mem[2326] = 247233
+mem[54001] = 1782454
+mem[41112] = 61297
+mem[45994] = 12285
+mask = 00X00010X0X1001111000010X0X1001XX10X
+mem[22080] = 50449
+mem[32446] = 69686
+mem[46129] = 6052251
+mem[45810] = 6931
+mem[2730] = 17348930
+mem[25557] = 22866081
+mem[53007] = 2662
+mask = 00000X1010111X0111011X01000X10X0XX01
+mem[26747] = 237030337
+mem[47589] = 912076
+mem[7333] = 105514
+mem[62613] = 1442076
+mem[293] = 1883
+mask = X1001X1010101111110XX010100000100X01
+mem[64864] = 522211793
+mem[381] = 395572639
+mem[39482] = 641
+mem[47108] = 37814
+mask = 00X00111101110111X001101001110XXX00X
+mem[16554] = 1304638
+mem[56666] = 189089562
+mem[12934] = 138931
+mem[63122] = 607569
+mem[37147] = 131399848
+mask = 0X1X11101XX11X0X11100111X100001111X0
+mem[24256] = 156773
+mem[14436] = 485469048
+mem[20781] = 376
+mem[23284] = 879110
+mem[2582] = 42478
+mem[39002] = 3578
+mask = 0000XX0X101010011XX000X0000X01100X01
+mem[40945] = 11048
+mem[36114] = 13782606
+mem[2325] = 185202507
+mem[33715] = 4806448
+mem[61649] = 3756998
+mem[55852] = 117
+mask = 01000000101X1011110010010XXX0XX11110
+mem[5881] = 13440134
+mem[22720] = 962895873
+mem[25142] = 11785
+mask = 0101011010111001010011100XX0011111XX
+mem[586] = 209
+mem[51207] = 145606
+mem[21220] = 62604
+mem[45100] = 34084913
+mem[30986] = 310031
+mem[56443] = 483530965
+mask = 0000100000X1X10X11X1100010100X011001
+mem[41487] = 38587945
+mem[21434] = 249215427
+mem[7230] = 111149021
+mask = X101X010XXX1100101X0X10100100111111X
+mem[40840] = 2606
+mem[63190] = 2447
+mem[60328] = 40915
+mem[45620] = 13499
+mask = 001X0010101110X1X1X0X11X0010X0X001X0
+mem[62719] = 785
+mem[19974] = 42859172
+mem[51864] = 44741
+mem[63056] = 27482866
+mask = X0X1X0101011X001X100101100101XX1X000
+mem[39205] = 10997188
+mem[14100] = 29987320
+mem[616] = 278639655
+mask = 0100000X10101X011X1111000X00X0111000
+mem[49278] = 610
+mem[9321] = 333537
+mem[22656] = 4066
+mem[8228] = 2791399
+mem[9251] = 3866
+mask = X00100X01011100X1X0XX000111011X00011
+mem[58260] = 459
+mem[18311] = 40779317
+mem[10291] = 3362
+mem[16865] = 1236
+mask = X100X000X010110111X0001100000001X011
+mem[1826] = 108687499
+mem[4087] = 243589
+mem[47489] = 474492676
+mem[4129] = 16244
+mem[29617] = 819406
+mem[43545] = 108512190
+mask = 010X0XX0101110X1X100X01X000X0X110100
+mem[57918] = 102433847
+mem[33825] = 9
+mem[372] = 230834
+mem[19591] = 7380
+mem[65409] = 98189
+mem[36391] = 3033
+mask = X101X000101111011000X10X100100100000
+mem[54029] = 347451
+mem[28001] = 82660784
+mask = 01X0000010101001X1000000X0X000110101
+mem[37266] = 1643
+mem[52294] = 242323894
+mem[40965] = 11451
+mem[52532] = 1191041
+mem[1994] = 1830445
+mem[16066] = 694
+mask = 0X100010X0X1XX0X01001X10X1100X110000
+mem[60293] = 92656839
+mem[8228] = 24889387
+mem[13951] = 25158

From cd627ea0f5e453786292ab0e074b2b122aaecf0c Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Mon, 14 Dec 2020 15:28:55 -0800
Subject: [PATCH 05/12] Completed day 13

---
 2020/days/day13.cpp | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/2020/days/day13.cpp b/2020/days/day13.cpp
index 576af53..db18feb 100644
--- a/2020/days/day13.cpp
+++ b/2020/days/day13.cpp
@@ -32,11 +32,14 @@
 #include "../misc/types.hpp"
 #include "../misc/print.hpp"
 
-struct Pair{ u64 id; usize index; };
+struct Pair{ i64 id; usize index; };
 
-auto find_least(u64 new_base, u64 new_loop, u64 req_base, u64 req_loop, u64 iter) -> u64 {
-	while ((new_base + ++iter * new_loop - req_base) % req_loop != 0);
-	return new_base + iter * new_loop;
+// f = a + n0 * b = c + n1 * d
+// f = req_base + n0 * req_loop = new_base + n1 * new_loop
+// Solve for the smallest integer value f such that this holds true
+auto find_least(i64 new_base, i64 new_loop, i64 req_base, i64 req_loop, i64 iter) -> i64 {
+	while ((req_base - new_base + ++iter * req_loop) % new_loop != 0);
+	return req_base + iter * req_loop;
 }
 
 auto day13() -> void {
@@ -55,7 +58,7 @@ auto day13() -> void {
 		while ((end = line.find(',', start)) != std::string::npos) {
 			id = line.substr(start, end - start);
 			if (id != "x") {
-				buses.push_back({ u64(std::stoi(line.substr(start, end - start))), index });
+				buses.push_back({ i64(std::stoi(line.substr(start, end - start))), index });
 			}
 			start = end + 1;
 			++index;
@@ -63,7 +66,7 @@ auto day13() -> void {
 		end = line.size();
 		id = line.substr(start, end - start);
 		if (id != "x") {
-			buses.push_back({ u64(std::stoi(line.substr(start, end - start))), index });
+			buses.push_back({ i64(std::stoi(line.substr(start, end - start))), index });
 		}
 	}
 	
@@ -78,18 +81,12 @@ auto day13() -> void {
 	}
 	print((id * minutes));
 
-	auto req_base = usize(0);
-	auto req_loop = usize(1);
+	auto req_base = usize(buses[0].index);
+	auto req_loop = usize(buses[0].id   );
 	for (auto i = usize(1); i < buses.size(); ++i) {
-		auto base_loop = usize(-1);
-		while ((++base_loop * buses[0].id + buses[i].index) % buses[i].id != 0);
-
-		auto rep_loop = usize(0);
-		while ((++rep_loop * buses[0].id) % buses[i].id != 0);
-
-		req_base = find_least(base_loop, rep_loop, req_base, req_loop, -1);
+		req_base = find_least(-buses[i].index, buses[i].id, req_base, req_loop, -1);
 		if (i < buses.size() - 1) {
-			req_loop = find_least(0, rep_loop, 0, req_loop, 0);
+			req_loop = find_least(0, buses[i].id, 0, req_loop, 0);
 		}
 		/*
 		required_base (rqb), required_loop (rql)
@@ -102,5 +99,5 @@ auto day13() -> void {
 		b0 * rql = b1 * rl < minimize and store in required loop
 		*/
 	}
-	print((req_base * buses[0].id));
+	print(req_base);
 }

From 5d3ec4087b18f013c29f88d0de10d228ee3f8e3d Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Mon, 14 Dec 2020 23:39:50 -0800
Subject: [PATCH 06/12] Completed day 15

---
 2020/Makefile           |  4 +--
 2020/days/day15.cpp     | 71 +++++++++++++++++++++++++++++++++++++++++
 2020/inputs/day15.input |  1 +
 3 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 2020/days/day15.cpp
 create mode 100644 2020/inputs/day15.input

diff --git a/2020/Makefile b/2020/Makefile
index 3860638..ea0c262 100644
--- a/2020/Makefile
+++ b/2020/Makefile
@@ -1,8 +1,8 @@
 day%.out: out/types.o misc/main.cpp days/day%.cpp
-	g++-10 -std=c++2a $(flags) -Dcurrent_day=$(@:.out=) days/$(@:out=cpp) misc/main.cpp out/types.o -o $@
+	g++-10 -O3 -std=c++2a $(flags) -Dcurrent_day=$(@:.out=) days/$(@:out=cpp) misc/main.cpp out/types.o -o $@
 
 day%_test.out: out/types.o misc/main_test.cpp days/day%.cpp
-	g++-10 -std=c++2a $(flags) -DTEST_BUILD -Dcurrent_day=$(@:_test.out=) days/$(@:_test.out=.cpp) misc/main_test.cpp out/types.o -o $@
+	g++-10 -O3 -std=c++2a $(flags) -DTEST_BUILD -Dcurrent_day=$(@:_test.out=) days/$(@:_test.out=.cpp) misc/main_test.cpp out/types.o -o $@
 
 days/day%.cpp:
 	cp 'misc/day.cpp.template' $@
diff --git a/2020/days/day15.cpp b/2020/days/day15.cpp
new file mode 100644
index 0000000..c33fb2a
--- /dev/null
+++ b/2020/days/day15.cpp
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <unordered_map>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+struct Pair{ u64 num; usize last; };
+
+auto day15() -> void {
+	auto last     = usize(0);
+	auto index    = usize(0);
+	auto sequence = std::unordered_map<u64, u64>();
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day15.input");
+		getline(file, line);
+		auto start = usize(0);
+		auto end   = usize(0);
+		auto num   = std::string();
+		while ((end = line.find(',', start)) != std::string::npos) {
+			num = line.substr(start, end - start);
+			sequence.insert_or_assign(u64(std::stoll(num)), ++index);
+			start = end + 1;
+		}
+		end = line.size();
+		num = line.substr(start, end - start);
+		sequence.insert_or_assign(u64(std::stoll(num)), ++index);
+	}
+	while (++index < 30000000) {
+		if (index == 2020) {
+			print(last);
+		}
+		if (sequence.contains(last)) {
+			auto new_last = index - sequence[last];
+			sequence[last] = index;
+			last = new_last;
+		} else {
+			sequence.insert_or_assign(last, index);
+			last = 0;
+		}
+	}
+	print(last);
+}
diff --git a/2020/inputs/day15.input b/2020/inputs/day15.input
new file mode 100644
index 0000000..3576b75
--- /dev/null
+++ b/2020/inputs/day15.input
@@ -0,0 +1 @@
+0,13,1,8,6,15

From 2b5a93b833e77ef8e06b51fa60829b9a239daa1c Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Tue, 15 Dec 2020 22:56:57 -0800
Subject: [PATCH 07/12] Completed day 16

---
 2020/days/day16.cpp     | 209 ++++++++++++++++++++++++++++++++
 2020/inputs/day16.input | 260 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 469 insertions(+)
 create mode 100644 2020/days/day16.cpp
 create mode 100644 2020/inputs/day16.input

diff --git a/2020/days/day16.cpp b/2020/days/day16.cpp
new file mode 100644
index 0000000..6c1989c
--- /dev/null
+++ b/2020/days/day16.cpp
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+struct Rule { u64 r11; u64 r12; u64 r21; u64 r22; };
+
+auto read_ticket(std::vector<u64> & ticket, const std::string & line) -> void {
+	auto start = usize(0);
+	auto end   = usize(0);
+	while ((end = line.find(",", end + 1)) != std::string::npos) {	
+		ticket.push_back(std::stoll(line.substr(start, end - start)));
+		start = end + 1;
+	}
+	end = line.size();
+	ticket.push_back(std::stoll(line.substr(start, end - start)));
+}
+
+auto matches_rule(const Rule & rule, u64 field) -> bool {
+	return (rule.r11 <= field && field <= rule.r12) || (rule.r21 <= field && field <= rule.r22);
+}
+
+auto remove_if_exists(std::vector<u64> & v, u64 search) -> bool {
+	auto low  = usize(0);
+	auto high = v.size();
+	while (low < high) {
+		auto index = (low + high) / 2;
+		if (v[index] == search) {
+			v.erase(v.begin() + index);
+			return true;
+		} else if (search > v[index]) {
+			low = index + 1;
+		} else {
+			high = index;
+		}
+	}
+	return false;
+}
+
+auto contains(std::vector<u64> & v, u64 search) -> bool {
+	auto low  = usize(0);
+	auto high = v.size();
+	while (low < high) {
+		auto index = (low + high) / 2;
+		if (v[index] == search) {
+			return true;
+		} else if (search > v[index]) {
+			low = index + 1;
+		} else {
+			high = index;
+		}
+	}
+	return false;
+}
+
+auto day16() -> void {
+	auto find        = std::vector<u64>();
+	auto rules       = std::vector<Rule>();
+	auto your_ticket = std::vector<u64>();
+	auto tickets     = std::vector<std::vector<u64>>();
+	{
+		auto line  = std::string();
+		auto file  = std::ifstream("inputs/day16.input");
+		auto index = usize(0);
+		while (getline(file, line) && line != "") {
+			auto rule  = Rule();
+			auto start = line.find(":") + 2;
+			auto end   = line.find("-");
+			rule.r11 = std::stoll(line.substr(start, end - start));
+			start = end + 1;
+			end   = line.find(" ", end);
+			rule.r12 = std::stoll(line.substr(start, end - start));
+			start = end + 4;
+			end   = line.find("-", end);
+			rule.r21 = std::stoll(line.substr(start, end - start));
+			start = end + 1;
+			end   = line.size();
+			rule.r22 = std::stoll(line.substr(start, end - start));
+			rules.push_back(rule);
+			if (line.find("departure") != std::string::npos) {
+				find.push_back(index);
+			}
+			++index;
+		}
+		getline(file, line);
+		getline(file, line);
+		read_ticket(your_ticket, line);
+		getline(file, line);
+		getline(file, line);
+		while (getline(file, line)) {
+			auto ticket = std::vector<u64>();
+			read_ticket(ticket, line);
+			tickets.push_back(std::move(ticket));
+		}
+	}
+	auto valid = std::vector<std::vector<u64>>();
+	{
+		auto foo = std::vector<u64>(your_ticket.size());
+		for (auto i = usize(0); i < your_ticket.size(); ++i) {
+			foo[i] = i;
+		}
+		for (auto i = usize(0); i < rules.size(); ++i) {
+			valid.push_back(foo);
+		}
+	}
+	auto sum = u64(0);
+	for (auto k = usize(0); k < tickets.size(); ++k) {
+		const auto & ticket = tickets[k];
+		auto invalid_ticket = false;
+		for (auto i = usize(0); i < ticket.size(); ++i) {
+			auto invalid_field = true;
+			for (auto j = usize(0); invalid_field && j < rules.size(); ++j) {
+				if (matches_rule(rules[j], ticket[i])) {
+					invalid_field = false;
+				}
+			}
+			if (invalid_field) {
+				sum += ticket[i];
+			}
+			invalid_ticket = invalid_ticket || invalid_field;
+		}
+		if (invalid_ticket) {
+			tickets.erase(tickets.begin() + k);
+			--k;
+		}
+	}
+	print(sum);
+
+	for (auto i = usize(0); i < tickets.size(); ++i) {
+		const auto & ticket = tickets[i];
+		for (auto j = usize(0); j < valid.size(); ++j) {
+			auto & v = valid[j];
+			for (auto k = usize(0); k < v.size(); ++k) {
+				if (!matches_rule(rules[j], ticket[v[k]])) {
+					v.erase(v.begin() + k);
+					--k;
+				}
+			}
+		}
+	}
+	for (auto i = usize(0); i < your_ticket.size(); ++i) {
+		auto cont_index = usize(0);
+		auto contained  = usize(0);
+		for (auto j = usize(0); j < valid.size(); ++j) {
+			if (contains(valid[j], i)) {
+				cont_index = j;
+				++contained;
+			}
+		}
+		if (contained == 1) {
+			for (auto j = usize(0); j < valid[cont_index].size(); ++j) {
+				if (valid[cont_index][j] != i) {
+					valid[cont_index].erase(valid[cont_index].begin() + j);
+					--j;
+				}
+			}
+		}
+	}
+
+	auto loop = true;
+	while (loop) {
+		loop = false;
+		for (auto i = usize(0); i < valid.size(); ++i) {
+			if (valid[i].size() == 1) {
+				for (auto j = usize(0); j < valid.size(); ++j) {
+					if (j != i) {
+						auto temp = remove_if_exists(valid[j], valid[i][0]);
+						loop = temp || loop;
+					}
+				}
+			}
+		}
+	}
+
+	auto product = u64(1);
+	for (auto i = usize(0); i < find.size(); ++i) {
+		product *= your_ticket[valid[find[i]][0]];
+	}
+	print(product);
+}
diff --git a/2020/inputs/day16.input b/2020/inputs/day16.input
new file mode 100644
index 0000000..3a28a2a
--- /dev/null
+++ b/2020/inputs/day16.input
@@ -0,0 +1,260 @@
+departure location: 34-724 or 735-974
+departure station: 40-521 or 534-950
+departure platform: 40-329 or 353-973
+departure track: 37-258 or 268-964
+departure date: 32-650 or 665-964
+departure time: 39-373 or 398-950
+arrival location: 42-431 or 447-952
+arrival station: 36-536 or 552-972
+arrival platform: 45-666 or 678-952
+arrival track: 49-836 or 852-952
+class: 35-600 or 623-953
+duration: 50-920 or 929-950
+price: 35-853 or 870-973
+route: 34-309 or 318-965
+row: 42-267 or 292-962
+seat: 46-632 or 642-954
+train: 47-746 or 754-960
+type: 32-406 or 423-963
+wagon: 37-797 or 810-973
+zone: 35-766 or 784-952
+
+your ticket:
+113,53,97,59,139,73,89,109,67,71,79,127,149,107,137,83,131,101,61,103
+
+nearby tickets:
+688,200,60,127,239,85,167,91,792,373,724,244,451,659,133,471,240,649,402,554
+686,424,398,148,91,729,425,231,318,711,209,166,665,105,227,579,229,937,876,495
+699,583,291,592,426,173,819,131,158,814,325,496,625,215,568,831,212,456,137,83
+62,134,362,84,404,722,599,898,555,99,318,364,462,208,83,368,723,185,383,884
+100,573,721,722,320,528,250,206,534,585,797,158,626,201,567,206,54,520,362,892
+944,901,891,906,556,122,71,564,558,474,195,325,580,224,570,879,604,759,600,361
+936,887,732,888,693,763,933,424,835,642,299,174,475,360,150,120,117,294,70,495
+556,209,820,68,164,69,447,397,647,128,137,127,164,328,98,241,736,134,908,562
+627,573,562,740,627,70,294,784,884,91,813,579,354,141,820,351,501,372,138,937
+172,894,647,169,763,466,398,755,556,945,229,307,906,369,197,19,787,489,580,64
+690,107,566,116,360,709,627,369,104,298,931,474,644,477,300,98,799,300,427,518
+61,355,872,448,405,825,528,555,500,600,123,882,123,50,645,919,85,401,712,309
+898,829,929,888,236,146,696,484,904,928,203,167,229,590,484,208,536,157,903,896
+475,552,717,206,898,986,630,255,764,580,885,583,447,81,130,165,688,557,763,158
+459,253,590,760,210,307,789,830,560,221,711,406,470,62,274,577,947,79,932,719
+241,450,123,462,622,167,572,933,120,477,427,623,630,898,761,366,74,453,711,581
+152,823,190,56,207,831,586,650,737,520,57,304,292,759,593,523,590,223,735,836
+160,917,931,83,820,585,252,138,630,118,649,308,171,320,484,739,479,453,263,156
+134,904,686,147,234,821,518,894,116,690,828,696,248,689,918,71,207,891,344,328
+91,133,722,87,934,764,256,632,323,738,490,557,166,929,881,58,690,977,915,235
+746,984,86,710,112,584,205,592,179,796,209,174,447,190,123,455,231,786,893,715
+218,461,649,304,892,945,891,586,198,221,755,305,368,206,129,490,462,996,424,88
+497,108,595,560,160,428,827,78,629,801,370,815,453,853,579,707,893,818,592,224
+463,810,631,118,176,716,924,305,788,877,78,404,702,722,912,324,696,702,485,877
+875,919,461,485,578,595,755,109,793,511,589,931,56,213,920,119,594,594,558,923
+683,124,786,878,933,788,15,61,255,200,452,885,449,707,101,555,325,110,358,405
+70,488,830,913,833,680,158,819,881,583,144,477,182,136,131,56,678,931,881,433
+679,353,226,425,895,827,96,652,111,84,70,473,116,241,404,740,111,77,717,699
+568,885,930,820,415,211,300,877,460,196,481,568,162,888,478,155,743,723,51,190
+61,853,793,309,165,497,720,128,176,424,478,356,741,566,151,168,923,82,710,243
+757,898,167,149,592,251,202,787,627,726,757,462,52,220,786,763,757,64,644,361
+746,564,574,560,351,172,429,574,105,84,689,932,224,365,229,504,881,195,116,484
+574,930,120,165,390,881,108,567,875,577,887,492,209,152,423,484,106,821,917,466
+69,326,754,890,204,248,618,930,938,722,915,463,703,879,598,593,149,583,886,398
+691,272,628,713,559,471,887,902,889,144,585,324,53,572,118,486,217,796,77,899
+198,580,147,92,217,623,919,812,694,577,223,697,909,292,130,758,902,73,110,614
+577,80,744,51,594,513,424,755,116,307,254,914,938,74,561,599,641,835,648,553
+228,939,820,503,676,876,934,189,149,692,625,468,215,567,319,126,829,483,893,894
+758,163,297,553,292,192,128,269,309,564,695,509,896,937,294,70,736,156,402,576
+326,885,566,238,562,904,500,471,431,885,129,938,587,784,983,115,89,123,201,64
+647,918,735,894,428,365,84,535,361,70,977,791,939,872,84,318,431,81,650,99
+490,180,128,117,560,176,170,711,535,691,89,289,564,515,493,910,692,253,557,705
+226,760,309,144,795,758,501,672,909,718,499,555,324,449,454,570,84,241,361,295
+69,455,248,146,289,99,756,632,505,93,786,143,106,746,222,486,517,679,821,370
+816,903,646,353,724,678,149,515,718,321,355,701,221,115,611,942,235,218,252,943
+904,463,485,697,64,127,454,694,225,796,195,169,112,695,363,880,157,239,806,824
+909,430,70,940,626,893,580,174,568,72,518,59,703,444,67,208,187,243,766,477
+232,569,738,910,664,487,198,469,90,206,151,428,597,701,624,877,99,171,915,133
+697,58,563,320,598,179,262,716,222,364,494,932,908,592,946,490,121,370,708,75
+90,400,57,132,761,573,179,433,467,202,81,554,423,327,625,822,108,429,74,319
+233,536,833,564,493,96,358,242,571,56,939,61,813,159,634,507,189,63,176,161
+942,303,463,295,793,830,135,892,717,491,948,357,687,554,303,321,81,172,846,117
+552,893,448,766,406,830,367,821,598,792,877,320,144,158,934,424,453,940,923,755
+365,82,679,227,525,362,561,589,746,87,239,499,914,298,102,371,447,896,185,238
+937,946,228,913,466,154,498,67,717,169,217,186,212,808,153,490,103,756,50,74
+137,165,624,242,424,890,467,201,665,521,362,233,706,916,225,806,472,158,353,738
+810,934,370,920,891,498,649,86,681,308,934,630,116,518,51,118,181,737,764,639
+94,459,601,626,400,218,724,90,724,251,248,519,558,249,110,823,214,482,450,218
+304,71,885,765,96,315,710,204,292,565,53,477,120,558,688,81,904,191,144,201
+328,400,111,494,635,882,590,918,357,597,686,789,89,241,229,681,823,784,877,222
+62,240,518,254,520,151,449,719,320,509,432,574,518,887,353,588,300,814,56,485
+871,536,369,497,230,535,453,119,915,302,872,303,199,632,797,459,430,426,611,572
+211,55,889,741,557,600,565,258,737,407,70,745,632,325,428,949,949,424,832,702
+185,238,189,696,742,495,176,225,908,549,495,488,487,491,785,232,935,491,579,218
+225,141,101,294,687,301,682,361,690,239,563,697,575,457,510,633,820,680,66,647
+428,931,181,324,162,13,896,891,53,237,754,205,915,100,220,87,104,878,241,94
+204,758,126,595,117,462,699,488,65,676,355,535,178,185,324,229,423,708,763,167
+692,78,562,589,179,102,430,943,852,757,921,64,302,73,129,474,595,167,190,745
+360,72,119,247,250,675,210,884,429,136,810,934,294,567,565,207,320,515,454,452
+214,161,128,468,937,580,484,479,764,0,217,896,252,593,208,929,193,784,460,174
+76,490,568,558,711,22,702,625,721,695,692,494,256,244,123,705,427,578,101,63
+298,794,931,325,813,938,104,196,80,999,89,243,195,681,365,51,916,581,891,907
+643,365,555,93,740,888,492,232,744,680,84,171,17,762,122,207,324,180,300,319
+811,755,95,500,83,902,703,429,192,942,908,514,744,535,687,898,67,931,314,737
+817,939,78,944,741,685,516,69,141,60,156,920,816,882,942,916,78,797,673,686
+109,875,438,913,698,244,892,705,399,252,448,402,361,128,892,559,464,872,744,357
+902,784,629,95,224,323,50,993,231,679,150,920,937,168,450,118,594,243,786,785
+927,456,115,901,129,455,829,155,182,579,645,248,53,740,699,836,403,596,215,883
+201,948,914,735,593,121,562,87,190,946,709,501,107,512,595,322,710,232,279,947
+449,109,901,916,755,133,58,251,591,763,639,61,205,737,301,718,200,719,187,453
+143,496,104,483,939,402,890,82,518,937,562,133,201,52,250,610,215,227,53,513
+134,694,424,307,312,499,363,879,944,487,448,721,911,599,718,588,191,499,788,510
+466,903,881,149,698,184,12,209,164,736,102,890,468,228,195,465,174,79,481,758
+220,593,697,360,225,146,938,79,369,948,294,799,708,427,485,911,577,83,472,168
+82,717,709,89,240,231,269,295,816,586,836,256,940,309,251,139,489,292,92,573
+796,229,424,463,19,824,300,590,755,583,81,189,949,690,63,516,324,648,372,812
+257,76,789,703,824,362,215,578,809,190,202,132,297,490,886,908,700,102,632,121
+503,565,373,891,199,364,600,489,120,561,572,918,493,899,477,179,659,890,178,702
+128,227,256,204,897,644,578,944,87,597,240,367,169,113,976,483,253,790,470,684
+404,648,506,718,449,802,509,458,878,198,817,820,141,597,53,193,598,629,215,794
+240,911,139,897,429,326,200,692,811,260,871,649,913,70,494,212,353,137,79,593
+63,574,483,893,62,709,717,699,365,898,949,638,68,901,786,306,591,583,242,680
+63,621,650,108,453,520,594,642,218,590,91,947,819,159,104,170,241,907,896,98
+555,233,715,508,695,156,650,145,458,154,231,119,212,898,882,732,367,219,746,911
+835,930,126,64,693,213,359,718,765,745,727,493,706,184,875,297,162,645,941,488
+404,717,314,712,232,62,211,625,50,479,683,457,459,743,59,294,506,948,722,492
+944,87,98,625,236,257,536,648,599,721,358,920,598,142,157,443,644,428,161,95
+257,573,267,431,484,406,145,556,631,597,821,355,245,145,941,594,456,876,740,741
+920,454,217,701,577,124,470,324,826,837,624,711,518,592,465,795,759,294,498,701
+711,224,483,213,908,497,190,896,202,247,522,150,400,222,719,399,138,944,895,165
+353,576,785,629,211,240,256,514,557,163,355,191,882,638,739,111,121,499,360,218
+424,180,690,321,578,494,587,937,361,833,267,683,491,816,169,703,242,201,357,792
+738,134,739,300,593,786,460,743,936,814,569,681,789,64,327,126,264,812,191,431
+426,915,477,323,716,144,112,63,217,438,900,632,724,294,873,181,468,627,900,164
+479,802,563,121,151,906,192,900,426,718,185,552,946,183,830,239,589,194,481,94
+791,649,469,255,724,66,293,112,610,589,898,363,252,109,425,754,368,431,789,148
+754,665,381,908,735,451,308,737,935,226,706,205,460,244,582,153,178,493,137,702
+321,597,137,599,940,99,109,300,357,130,184,686,996,710,96,178,322,477,226,176
+153,890,836,24,888,643,737,902,597,572,504,486,573,878,251,124,184,600,685,217
+59,742,582,792,229,432,117,920,355,252,917,354,488,205,125,191,110,682,216,456
+324,367,186,203,912,564,870,881,553,365,605,476,326,828,586,154,400,104,579,431
+96,491,758,426,835,489,807,507,811,520,536,298,329,326,295,92,692,515,79,947
+535,682,139,232,938,595,552,824,71,630,831,558,258,448,814,949,222,995,364,828
+898,912,723,464,723,160,194,344,710,113,167,710,195,163,822,735,198,877,224,698
+360,82,111,146,430,703,328,880,406,200,929,64,467,726,647,482,225,449,477,709
+694,81,5,513,590,212,168,399,117,366,59,99,888,354,131,912,177,558,831,594
+520,363,529,159,358,935,202,648,372,940,89,467,483,128,220,138,628,519,252,171
+71,101,514,937,510,946,320,402,480,91,486,584,687,91,113,228,80,648,525,308
+693,494,171,17,114,516,370,320,307,624,356,591,812,156,497,238,557,905,889,820
+301,426,994,218,62,205,797,583,236,552,686,91,760,230,509,823,475,467,160,698
+597,399,51,454,487,666,728,692,874,477,447,318,237,372,453,744,250,458,894,234
+626,95,800,195,702,789,684,571,829,105,147,712,365,75,248,293,234,140,134,166
+576,489,224,159,947,323,116,403,180,683,795,874,197,400,446,720,930,237,240,401
+679,492,22,468,98,594,474,224,328,197,471,471,366,784,472,448,210,686,224,943
+915,471,760,721,587,492,893,327,580,826,807,370,872,684,357,875,937,354,318,361
+246,835,582,831,470,888,881,826,22,739,296,231,784,722,228,144,513,488,879,195
+913,175,109,687,208,207,64,514,819,508,590,489,17,474,566,873,97,481,901,239
+77,192,105,501,70,699,255,136,824,503,655,504,256,194,715,944,326,946,647,448
+189,586,213,294,252,884,935,500,88,309,193,993,814,69,944,810,212,225,719,553
+463,403,568,793,833,921,307,497,593,552,586,741,65,643,66,692,763,143,765,785
+454,889,935,152,434,142,818,366,104,197,184,242,597,895,224,117,325,212,517,794
+717,154,62,135,795,405,743,9,498,219,177,707,103,625,554,61,303,228,194,697
+63,72,882,362,193,754,484,822,236,687,685,296,197,821,925,195,818,897,796,456
+584,463,489,209,232,480,907,919,453,354,281,784,92,938,592,99,646,813,818,700
+250,373,586,229,690,136,101,548,219,358,759,132,370,829,174,884,820,574,459,117
+575,453,945,631,219,301,398,128,787,250,112,594,919,723,808,302,94,812,292,518
+713,106,590,194,361,759,318,123,890,710,122,242,473,293,384,692,145,792,901,428
+132,940,325,931,559,761,907,901,521,92,723,115,815,367,730,487,689,369,573,554
+81,61,566,932,141,349,255,97,233,115,795,816,821,218,319,186,73,632,116,145
+743,629,246,246,800,457,202,534,702,77,739,735,188,934,623,71,912,247,252,100
+800,79,569,167,934,715,916,586,225,562,479,56,705,115,836,912,829,793,71,425
+362,485,689,788,487,301,882,86,373,767,902,600,214,132,825,170,884,629,877,100
+681,876,878,198,539,102,475,919,699,883,762,212,149,457,939,154,247,62,724,918
+915,95,896,832,708,278,826,470,451,512,560,690,71,172,739,181,515,514,144,504
+364,485,146,889,190,329,174,465,719,254,710,925,89,58,690,99,939,404,482,791
+933,51,927,453,597,179,454,403,890,690,495,57,473,690,679,878,175,57,739,320
+249,114,989,933,257,703,328,204,694,431,240,880,501,893,366,53,97,886,810,587
+792,826,823,75,261,91,144,892,140,222,448,373,580,308,581,482,899,578,114,628
+587,129,105,66,515,205,590,89,502,998,940,584,454,256,360,931,118,164,256,693
+877,744,242,329,461,394,568,449,700,89,792,625,597,503,196,65,828,814,431,914
+61,91,700,536,697,114,131,481,499,365,493,473,678,934,120,598,355,826,231,277
+876,307,216,712,928,518,573,363,303,690,708,628,872,836,207,139,163,65,666,467
+494,483,449,328,194,880,258,113,107,932,552,210,824,301,74,396,568,130,883,787
+144,707,507,597,60,197,129,698,555,320,329,791,942,792,530,96,91,596,936,684
+235,558,479,456,554,657,684,878,216,426,828,693,914,258,121,476,320,104,78,766
+830,558,161,536,183,63,626,686,920,273,820,180,794,705,140,825,216,562,648,713
+209,296,788,743,296,75,882,306,298,575,247,784,487,3,707,197,716,648,494,600
+320,703,306,181,707,622,247,626,177,574,666,460,910,401,724,117,370,231,710,302
+66,912,474,186,137,755,437,118,910,481,55,884,500,579,449,870,108,183,74,702
+898,398,128,431,700,936,623,500,51,591,789,127,89,145,164,998,179,736,704,194
+181,56,574,485,948,853,171,223,207,241,179,479,935,616,140,794,230,831,557,320
+282,695,61,919,743,481,877,885,160,126,130,595,71,448,589,398,810,631,212,98
+583,178,145,172,595,295,132,149,284,162,111,398,154,796,595,171,113,357,429,121
+875,447,180,65,301,425,168,949,706,104,790,448,590,823,120,581,730,362,320,907
+796,249,501,202,130,788,520,142,574,461,192,708,133,79,742,642,717,50,727,903
+175,301,110,685,117,466,186,927,632,742,451,328,169,683,103,931,514,359,72,227
+710,643,490,794,877,99,208,527,53,127,169,785,579,449,784,555,714,878,679,130
+643,13,167,178,828,423,227,623,566,299,486,499,680,702,96,584,364,534,189,941
+882,493,571,76,935,240,230,468,599,337,373,138,564,704,791,79,104,242,580,786
+766,766,240,916,759,580,453,164,325,909,743,604,216,648,92,745,909,122,62,244
+197,563,250,110,236,78,825,837,627,493,492,250,871,487,893,763,318,194,827,487
+308,362,888,147,489,7,132,474,58,309,160,235,325,109,895,237,400,692,82,872
+482,757,566,517,564,584,905,58,68,911,735,690,476,111,651,478,915,81,220,765
+569,405,826,504,369,711,165,119,745,885,204,215,83,285,402,829,66,148,254,167
+52,107,793,510,61,996,631,102,227,479,743,916,145,76,251,225,138,70,328,718
+67,569,104,642,493,705,321,896,476,813,370,882,579,425,235,120,486,933,504,0
+919,148,129,482,52,908,236,497,895,641,119,892,691,102,164,193,645,233,192,737
+302,235,80,875,569,596,179,208,58,476,235,250,190,168,160,185,297,926,354,448
+70,354,828,568,242,186,404,320,354,574,86,792,763,137,827,218,557,286,235,834
+301,298,637,901,505,873,765,498,565,230,536,826,516,570,233,474,786,129,162,145
+712,229,242,501,816,243,96,509,708,365,52,829,190,505,697,317,565,403,556,817
+941,820,113,512,877,641,899,74,474,69,228,143,700,164,147,297,559,584,75,499
+984,784,472,357,757,573,816,894,206,181,240,82,832,596,139,127,356,452,184,447
+89,895,258,169,208,883,629,315,892,902,233,137,598,929,502,580,450,119,942,199
+328,895,492,367,748,685,598,599,405,482,243,320,486,77,575,72,406,939,157,293
+188,943,662,195,553,683,709,483,179,562,178,665,944,824,517,90,933,325,117,898
+644,153,904,138,932,508,826,99,926,200,486,56,363,210,793,368,709,469,233,325
+785,300,58,833,915,643,447,731,491,585,454,491,405,486,204,360,929,99,255,302
+207,831,558,759,499,241,252,789,944,393,707,555,125,249,373,720,327,887,514,302
+131,826,481,795,710,577,474,423,54,144,152,72,584,827,109,284,96,78,700,153
+229,556,499,164,88,698,141,513,190,96,293,240,254,257,816,649,156,302,432,699
+424,187,479,244,690,570,505,100,154,648,166,125,292,458,810,926,714,898,569,197
+577,756,512,135,715,406,701,687,637,91,698,302,817,875,114,593,91,510,467,142
+473,460,182,112,777,101,878,78,215,161,222,565,624,203,318,883,491,573,306,821
+870,497,121,718,510,292,92,159,363,78,909,509,132,517,554,913,94,118,458,798
+369,505,351,308,101,201,882,720,788,765,931,818,220,945,702,181,815,895,517,628
+500,910,123,936,493,111,73,564,501,173,473,307,558,510,266,111,897,217,147,301
+766,700,899,517,83,139,118,666,89,129,122,826,599,468,492,849,686,949,695,111
+252,122,241,460,200,367,629,893,919,680,483,440,480,87,631,451,465,241,212,462
+565,711,121,918,424,484,899,722,498,243,792,787,158,329,702,775,357,189,189,824
+462,679,138,294,252,250,234,478,302,618,459,570,210,182,827,513,585,476,789,148
+891,105,181,163,256,116,125,737,588,889,534,471,993,226,932,581,187,788,135,459
+68,222,630,691,153,588,882,260,89,71,297,816,576,830,106,697,941,490,94,719
+52,449,128,204,482,211,931,911,242,698,479,818,495,703,181,183,825,561,656,832
+296,172,118,790,431,357,502,87,881,705,746,816,301,118,693,263,703,172,91,557
+406,556,52,302,248,155,534,220,467,224,483,257,121,741,761,885,279,237,398,784
+257,471,573,153,371,258,461,181,492,789,326,835,291,63,176,162,935,176,353,60
+880,914,515,362,497,137,465,70,235,511,306,194,521,924,740,815,466,305,792,98
+149,306,354,895,717,215,54,703,329,74,62,934,208,986,112,212,694,297,511,178
+589,517,516,367,328,68,678,557,785,834,68,97,744,198,400,876,88,986,906,690
+736,763,821,217,992,904,822,193,719,827,942,456,894,370,492,255,163,211,167,355
+795,135,83,765,484,260,760,150,699,495,138,108,563,306,563,198,577,794,256,503
+518,912,193,431,97,699,109,805,553,403,822,931,682,706,520,57,111,220,324,490
+187,101,498,508,895,101,225,592,455,697,560,185,155,511,703,558,688,113,70,656
+148,599,302,126,469,829,191,218,766,87,140,583,578,827,520,701,53,592,817,18
+645,646,152,469,123,222,746,897,984,127,360,745,789,874,898,788,578,111,368,578
+737,558,898,456,448,194,645,694,666,311,74,108,793,813,451,947,501,853,575,242
+988,212,920,72,693,95,471,882,144,79,643,50,587,829,505,562,237,496,885,827
+929,145,403,715,513,871,687,93,625,258,368,326,870,684,710,503,570,920,634,828
+853,198,501,790,904,486,252,609,593,119,714,137,166,51,297,593,701,560,472,685
+452,597,428,300,733,161,207,514,570,93,556,827,448,428,447,303,75,814,302,164
+205,144,492,214,498,710,121,598,650,533,534,823,247,712,83,678,494,172,937,623
+625,211,95,158,465,918,883,364,89,198,74,93,193,481,763,653,301,201,153,643
+134,921,458,789,353,796,173,534,398,88,151,87,300,763,237,456,366,933,358,572
+563,600,168,584,513,98,871,920,360,249,367,762,89,517,479,448,441,502,720,364
+823,492,484,794,872,874,338,181,693,372,77,306,791,508,785,508,472,933,50,756
+307,193,649,793,850,594,220,572,625,74,835,240,150,327,188,711,371,228,245,578
+626,232,497,691,327,943,636,202,321,698,790,682,447,577,371,593,132,820,491,898
+234,823,485,146,84,99,520,236,700,663,201,690,296,120,712,299,105,870,59,649
+448,765,62,297,462,258,660,482,920,591,689,890,821,211,76,586,50,874,99,644
+578,649,819,465,104,884,744,899,873,76,144,553,935,173,949,675,593,826,71,100
+573,163,451,329,215,398,200,650,368,906,354,164,721,297,718,789,4,371,309,136
+508,174,700,555,908,59,902,767,428,576,404,361,898,792,787,498,76,148,503,453
+192,882,896,124,207,299,558,215,822,207,227,80,517,64,338,877,111,564,86,678
+68,920,510,89,822,482,161,638,230,716,885,482,678,698,488,501,501,871,72,120

From dcdb4a727432304211600802a150b0682ded0c90 Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Wed, 16 Dec 2020 22:46:56 -0800
Subject: [PATCH 08/12] Completed day 17

---
 2020/days/day17.cpp     | 163 ++++++++++++++++++++++++++++++++++++++++
 2020/inputs/day17.input |   8 ++
 2 files changed, 171 insertions(+)
 create mode 100644 2020/days/day17.cpp
 create mode 100644 2020/inputs/day17.input

diff --git a/2020/days/day17.cpp b/2020/days/day17.cpp
new file mode 100644
index 0000000..a016751
--- /dev/null
+++ b/2020/days/day17.cpp
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <array>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+constexpr auto CYCLES = 6;
+constexpr auto BUFFER = CYCLES + 1;
+
+auto neighbor3d_count(const auto & pocket, i32 x, i32 y, i32 z) -> usize {
+	auto count = usize(0);
+	for (auto i = i32(-1); i < 2; ++i) {
+		for (auto j = i32(-1); j < 2; ++j) {
+			for (auto k = i32(-1); k < 2; ++k) {
+				count += (i != 0 || j != 0 || k != 0) && pocket[x + i][y + j][z + k];
+			}
+		}
+	}
+	return count;
+}
+
+auto neighbor4d_count(const auto & pocket, i32 w, i32 x, i32 y, i32 z) -> usize {
+	auto count = usize(0);
+	for (auto i = i32(-1); i < 2; ++i) {
+		for (auto j = i32(-1); j < 2; ++j) {
+			for (auto k = i32(-1); k < 2; ++k) {
+				for (auto l = i32(-1); l < 2; ++l) {
+					count += (i != 0 || j != 0 || k != 0 || l != 0) && pocket[w + l][x + i][y + j][z + k];
+				}
+			}
+		}
+	}
+	return count;
+}
+
+auto day17() -> void {
+	auto pocket = std::vector<std::vector<std::vector<std::vector<bool>>>>();
+	{
+		auto lines = std::vector<std::string>();
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day17.input");
+		while (getline(file, line)) {
+			lines.push_back(line);
+		}
+
+
+		pocket = std::vector<std::vector<std::vector<std::vector<bool>>>>(BUFFER * 2 + 1);
+		for (auto w = usize(0); w < pocket.size(); ++w) {
+			pocket[w] = std::vector<std::vector<std::vector<bool>>>(lines[0].size() + BUFFER * 2);
+			for (auto i = usize(0); i < pocket[0].size(); ++i) {
+				auto vec = std::vector<std::vector<bool>>(lines.size() + BUFFER * 2);
+				for (auto j = usize(0); j < vec.size(); ++j) {
+					vec[j] = std::vector<bool>(BUFFER * 2 + 1);
+					if (w == BUFFER && i >= BUFFER && i < BUFFER + lines[0].size() && j >= BUFFER && j < BUFFER + lines.size()) {
+						vec[j][BUFFER] = lines[j - BUFFER][i - BUFFER] == '#';
+					}
+				}
+				pocket[w][i] = std::move(vec);
+			}
+		}
+	}
+
+	{
+		auto pockets = std::array<std::vector<std::vector<std::vector<bool>>>, 2>{ pocket[BUFFER], pocket[BUFFER] };
+		auto bit = false;
+		for (auto i = usize(0); i < CYCLES; ++i) {
+			auto & read  = pockets[bit];
+			auto & write = pockets[bit = !bit];
+			for (auto x = i32(1); x < read.size() - 1; ++x) {
+				for (auto y = i32(1); y < read[0].size() - 1; ++y) {
+					for (auto z = i32(1); z < read[0][0].size() - 1; ++z) {
+						auto neighbors = neighbor3d_count(read, x, y, z);
+						if (read[x][y][z] && (neighbors < 2 || neighbors > 3)) {
+							write[x][y][z] = false;
+						} else if (!read[x][y][z] && neighbors == 3) {
+							write[x][y][z] = true;
+						} else {
+							write[x][y][z] = read[x][y][z];
+						}
+					}
+				}
+			}
+		}
+
+		auto & pocket = pockets[bit];
+		auto count = usize(0);
+		for (auto i = usize(0); i < pocket.size(); ++i) {
+			for (auto j = usize(0); j < pocket[0].size(); ++j) {
+				for (auto k = usize(0); k < pocket[0][0].size(); ++k) {
+					count += pocket[i][j][k];
+				}
+			}
+		}
+		print(count);
+	}
+
+	{
+		auto pockets = std::array<std::vector<std::vector<std::vector<std::vector<bool>>>>, 2>{ pocket, pocket };
+		auto bit = false;
+		for (auto i = usize(0); i < CYCLES; ++i) {
+			auto & read  = pockets[bit];
+			auto & write = pockets[bit = !bit];
+			for (auto w = i32(1); w < read.size() - 1; ++w) {
+				for (auto x = i32(1); x < read[0].size() - 1; ++x) {
+					for (auto y = i32(1); y < read[0][0].size() - 1; ++y) {
+						for (auto z = i32(1); z < read[0][0][0].size() - 1; ++z) {
+							auto neighbors = neighbor4d_count(read, w, x, y, z);
+							if (read[w][x][y][z] && (neighbors < 2 || neighbors > 3)) {
+								write[w][x][y][z] = false;
+							} else if (!read[w][x][y][z] && neighbors == 3) {
+								write[w][x][y][z] = true;
+							} else {
+								write[w][x][y][z] = read[w][x][y][z];
+							}
+						}
+					}
+				}
+			}
+		}
+
+		auto & pocket = pockets[bit];
+		auto count = usize(0);
+		for (auto i = usize(0); i < pocket.size(); ++i) {
+			for (auto j = usize(0); j < pocket[0].size(); ++j) {
+				for (auto k = usize(0); k < pocket[0][0].size(); ++k) {
+					for (auto l = usize(0); l < pocket[0][0][0].size(); ++l) {
+						count += pocket[i][j][k][l];
+					}
+				}
+			}
+		}
+		print(count);
+	}
+}
diff --git a/2020/inputs/day17.input b/2020/inputs/day17.input
new file mode 100644
index 0000000..9883294
--- /dev/null
+++ b/2020/inputs/day17.input
@@ -0,0 +1,8 @@
+###...#.
+.##.####
+.####.##
+###.###.
+.##.####
+#.##..#.
+##.####.
+.####.#.

From 9133abeffe62d2fa9b5ebf210d318291626c4dc9 Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Thu, 17 Dec 2020 23:58:33 -0800
Subject: [PATCH 09/12] Completed day 18

---
 2020/days/day18.cpp     | 128 ++++++++++++++
 2020/inputs/day18.input | 377 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 505 insertions(+)
 create mode 100644 2020/days/day18.cpp
 create mode 100644 2020/inputs/day18.input

diff --git a/2020/days/day18.cpp b/2020/days/day18.cpp
new file mode 100644
index 0000000..c459a7a
--- /dev/null
+++ b/2020/days/day18.cpp
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+auto evaluate_part1(const std::string & equation, usize & index) -> u64 {
+	auto value     = u64(0);
+	auto operation = 0;
+	while (equation[index] != ')') {
+		if ('0' <= equation[index] && equation[index] <= '9') {
+			auto end = index;
+			while ('0' <= equation[++end] && equation[end] <= '9');
+			if (operation == 0) {
+				value += std::stoll(equation.substr(index, end - index));
+			} else {
+				value *= std::stoll(equation.substr(index, end - index));
+			}
+			index = end;
+		} else if (equation[index] == '+') {
+			operation = 0;
+			index += 2;
+		} else if (equation[index] == '*') {
+			operation = 1;
+			index += 2;
+		} else if (equation[index] == '(') {
+			if (operation == 0) {
+				value += evaluate_part1(equation, ++index);
+			} else {
+				value *= evaluate_part1(equation, ++index);
+			}
+		} else if (equation[index] == ' ') {
+			++index;
+		}
+	}
+	++index;
+	return value;
+}
+
+auto evaluate_part2(const std::string & equation, usize & index) -> u64;
+auto evaluate_part2_addition(const std::string & equation, usize & index) -> u64;
+auto evaluate_part2_factor(const std::string & equation, usize & index) -> u64;
+
+auto evaluate_part2(const std::string & equation, usize & index) -> u64 {
+	auto value1 = evaluate_part2_addition(equation, index);
+	if (++index < equation.size() && equation[index] == '*') {
+		auto value2 = evaluate_part2(equation, index += 2);
+		return value1 * value2;
+	}
+	--index;
+	return value1;
+}
+
+auto evaluate_part2_addition(const std::string & equation, usize & index) -> u64 {
+	auto value1 = evaluate_part2_factor(equation, index);
+	if (++index < equation.size() && equation[index] == '+') {
+		auto value2 = evaluate_part2_addition(equation, index += 2);
+		return value1 + value2;
+	}
+	--index;
+	return value1;
+}
+
+auto evaluate_part2_factor(const std::string & equation, usize & index) -> u64 {
+	auto value = u64(0);
+	if (equation[index] == '(') {
+		value = evaluate_part2(equation, ++index);
+		++index;
+	} else {
+		auto end = index;
+		while ('0' <= equation[++end] && equation[end] <= '9');
+		value = std::stoll(equation.substr(index, end - index));
+		index = end;
+	}
+	return value;
+}
+
+auto day18() -> void {
+	auto equations = std::vector<std::string>();
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day18.input");
+		while (getline(file, line)) {
+			equations.push_back(line + ')');
+		}
+	}
+	auto sum = u64(0);
+	for (auto i = usize(0); i < equations.size(); ++i) {
+		auto index = usize(0);
+		sum += evaluate_part1(equations[i], index);
+	}
+	print(sum);
+
+	sum = u64(0);
+	for (auto i = usize(0); i < equations.size(); ++i) {
+		auto index = usize(0);
+		sum += evaluate_part2_factor('(' + equations[i], index);
+	}
+	print(sum);
+}
diff --git a/2020/inputs/day18.input b/2020/inputs/day18.input
new file mode 100644
index 0000000..ea3aedd
--- /dev/null
+++ b/2020/inputs/day18.input
@@ -0,0 +1,377 @@
+9 * 8 + 2 + (4 * (2 * 2 + 9 * 2) * 9 * 3 * 8) + 8 * 5
+8 * (9 + 5 + 5 * 6 + 8 * 3) * 5 * 7 * 4 + 9
+(9 + (2 * 6 + 7 * 5)) * (7 + 7 * 5 + (6 + 2 + 6) * (7 * 8 * 8 + 9)) + 4 * 2
+((8 + 3 * 6 * 2) * 9 + 3) + 5 + 6 * 3
+6 * (9 + 6 * (7 + 4 + 2 + 5 + 6) * 7 + 3 * (5 * 8 * 6 + 6 * 7 * 8)) + (8 * 8 + 4) + (5 * (2 + 9) * 8) * 4 * 2
+(8 * 6 + 8) + 6 * 8 * (9 * (6 + 8 * 3 + 8) + (7 * 9 * 6 * 3) * 3 + 8 * 4)
+3 * 4 * 8 * 7 + (4 + 5 + 8 * (3 + 3 + 3 * 6) + 4 + (3 * 8 * 8 * 6)) + (8 + 8 * (4 + 2 + 5 * 8 + 9))
+8 * ((2 + 8 * 8 * 2 + 3) * 8 + 7 * 4) * (5 + 6) + 4 * 7
+5 * (6 * 2 * 3 + 9) * (3 + 3 * (6 + 6 * 3) + 3 * 5 * 2)
+5 * (7 + (2 * 7 * 2 * 6) * (9 * 7 + 8 * 7)) * 8 * 5
+4 * (7 + 2 + (2 * 5 + 2 * 4 * 8))
+6 * 3 + (7 * 3)
+8 * 9 + (3 + (3 * 5 + 3 * 8 * 8) + 8) + 3
+2 * 3 + (4 + 7 + 2)
+8 + 2 * 6 + 9 + 7 * (9 + (9 * 9) + 3 * (8 * 3 * 7) + 2 + (7 + 5 * 5 * 2 + 9))
+6 + 9 * (6 * 9 + 5 + 7)
+3 * (5 + 5)
+(4 + 9 * 7 * 8 * (5 * 6 + 4 * 7)) * 6
+5 + (3 * 7 + 5)
+(5 + 2 * (3 * 2 + 6 + 3)) + (2 * 7 * 9 * 2) * (8 * 3 * 5)
+2 * ((3 + 7 + 4) * 4 + 3 * 3) + 4 + 2
+(8 * 3) * 5 * 9 + (7 + 8 + 4 * (2 * 8 + 8 * 3)) + 3
+5 + (4 * 8) + 3 + 7 + 6
+4 + 9 + 4 + 5 * 9 + (9 + 2 * 2 * (5 * 6) + 8)
+9 + (5 + (6 + 6 * 4) * 8 * (7 * 9 * 3 + 8 * 3)) * 5 * 9 + 6
+2 + 6 * 4 + ((9 + 8 + 6 + 9) * 7 + 2 + 5 * 3 + 3) * (9 * (5 * 4 + 4) + 3 * 7 + (6 + 4 * 9 + 5 + 4 + 5)) * 4
+3 * 6 + 4 + (7 * (5 + 5 * 5) + (3 * 4 * 7 + 3) * 5 + 5 * 5)
+8 + 8 * 7 + (6 + (9 + 2)) + 4
+2 * 3 * (6 + (2 * 9) + 7 * 3 * 3 + 6) + 6 + 4
+8 + 8 + 8 * ((7 + 5 + 9) * 6 + 9 + 9)
+(3 * 7) + 5 * (9 * 6) * 2 + (9 * 9)
+7 + 8 + 6 + 6 * 4 * 2
+6 * 3 + 5 * (4 * (6 + 3 + 5 * 9 * 8) * (4 + 7) * (2 * 6) + 3 * 9) * 9
+((2 * 2 + 9 * 4) + 3 + (3 + 5)) * 6 + 8 * 9
+4 + 6 + (3 * (2 + 2 + 2 + 2) + 6 + 9 + 3 + (5 + 9 + 9 + 6))
+(5 + (3 * 7 * 7 + 7 * 2)) + (9 * 3 * 6 + 8 + 5 + 8) * 8 * 5 + 9
+4 + 6 * 7 + (2 + 3 + 4 * 8 * (3 * 4 * 9 * 2 * 5 * 6)) + 9
+4 + ((6 + 9) * 7 * (8 * 7 * 4 + 7 + 5 + 3) * 9 * 6) * 9 + (3 * (6 * 7 + 6 + 2 * 4) * 3 + (4 + 8 + 9 + 7 + 8 + 9) * 6 + (6 + 9 + 2 * 3)) * 7
+6 * ((8 * 6 * 7 * 7 * 9 * 7) + (9 + 8 * 5 * 8) + 5 * (9 + 2 * 6))
+2 + 8 + 8 + 9 * (9 * (7 + 8 * 4 + 4 * 8 + 6))
+2 * 6 * 4 * ((2 * 2 * 6 * 7 + 3 * 8) + (7 + 8 + 7) * 4 + 9) + 7 * (4 + (5 + 7 * 9))
+(6 * (5 + 6 + 3 * 5 + 4 + 2) + 9 * 2 * 6) + 2 * (8 * (6 * 3)) * 2 + 4
+9 + 5 + 5 * ((3 * 3 * 8) * (2 * 9 + 7) * 4 + 4) * (3 + 6 * 5)
+((9 * 8 * 8) * 4 * 6 * 7) + 4 + 4 + 2 * 7 * 8
+(5 * 4) + 6 * 3 + 8 * 2
+7 * 8 * 2 + 2 * 7
+2 * 2 * 9 + 4 * ((4 + 3 * 5 * 6 + 5 + 8) + 4 + 7 * 6 + (4 + 6 * 9 * 5 + 5)) + 3
+3 + (2 * 3 * 9 * 7 * (5 + 6 * 6 * 5 + 4) + 7)
+(9 * 7 * 7 * (9 * 9) + 5 + 3) + 9 * 7 + 9 + 9 + (3 * 9 * 2 * 2 + 2)
+7 + 3 + (4 * 6 + (5 * 6 * 2)) * 3
+9 + (3 * (8 * 5 * 6 + 8)) * ((8 + 6 + 9 + 8 + 5 * 6) + 6) + 6 + 4 * 2
+3 + 2 * 6 + 8 * 7 * (9 * 6 + 3 * 7)
+4 * 9 + 4 + 7 + ((9 * 8) + 7 + 8 * 9 * 4) * 9
+(9 * 3 * 7 * 6 + 3) * 3 + 5 + (4 + 7 + 9) + 2 * 2
+4 * 6 + ((6 + 5 + 3 + 8 + 7) + 5 + 6 + 2 + 5) * 3
+6 + 3 * 6 + 8 * 2 + 6
+(6 + 6 * (8 * 8 + 7 * 8 + 2)) + 9 * (6 + (7 * 9) + (6 + 6 + 3) + 8 * 5 + 6) * 5
+9 + 4 * (5 * 4 * 5 + 4 * (4 + 7 * 9) + 2) + (6 * 7 * (2 + 5 * 5 * 6) * 8) + 8 * 3
+3 * 4 * 6 * 9 * 7 + ((9 + 9 + 2) + (8 * 2 + 9 + 2 + 5) * 9 + (9 + 7 * 5 * 3 + 7 + 8) + 4)
+(4 * 8 + 4 + 9 * 8) * 7 * 8 * 5 + 6 + 2
+7 * (9 * (9 * 3 * 5) * 7 + 5 * 3 + 9) + 3
+(6 * (9 + 4) * 4 * (5 * 7 * 4 + 6 * 5)) * 2 + 9 + 5
+4 + ((5 + 3 * 7 * 8 + 3) + (8 * 3 + 5 + 9 * 7 * 8) + 5 + 3 + (2 + 3 * 7 + 2) + 8)
+(2 * 4 * 7 * 2 + 7 * (3 + 8 + 9 + 7 + 9)) * 3 * (9 + (6 + 5 * 7 * 7) * 2 + (4 * 3 * 5 * 8 * 2 + 6)) * 6 + (8 + 6 + (9 * 6))
+4 * 9 + (8 * (6 + 5 + 7 * 8 * 7 * 3) + 9 * 8 * 5) + 5
+2 * 6 + (5 * (6 * 9 * 8 * 9) * 3) + 4 + 8
+2 * 8
+(8 * (4 + 6 + 5 + 3 * 5) + (2 * 5 * 8 * 9 + 3 + 6) * 2 * 6 * 2) * 3 + (8 + 6 * 2 + 4 + 7)
+((6 + 4 * 8) * 3 * 5) * 3
+(7 * 8 + 5 + 5) * 8 + (5 * 7 * 8 * 9) * (8 + 6 + (3 + 9)) * 5
+7 * (6 * (6 + 8 + 6) * 7 * 3 * 9 + (9 + 8 * 5 * 3 * 6)) + 5 + 5
+3 + (6 * 3 + 7) * 4
+(7 + 8 + 3 + 5 * 2) + 2
+4 + (7 * 7 * 3 + (6 + 6) * 8 + 6) + (4 * (9 + 7 + 5 * 4) * 2) * 6 * (2 * 3) + 4
+2 * ((3 + 5 * 6 + 6 + 3 * 6) + 5) + 5
+4 * 6 + (3 + 2 + 2 * 6 * 4 * 5) * 6 + (9 + 2 + 2 + (9 * 2 * 2 * 3 + 8) * (7 + 6 + 3 + 5)) + 8
+4 * 3 * (6 + 8 + (6 + 2 + 4 * 7 * 7 * 6) * 9 * 7) * 7
+8 * (8 * 2 + 8 + (3 * 2))
+5 + ((4 * 8) * (3 * 9 * 8 * 8) * 6 * 2 * 2 + 6) + 3
+2 * 7 * 6 * (7 * 8 + 4 + 5) * (2 * 5) + 7
+3 * 5 * (5 * 2 + 6 + 9 + 8 * 4)
+(3 + 3 + 8) + 3 * 8 + 6
+2 * (9 * (2 * 2 + 4 * 2 + 8) * 5) * 4
+3 * (2 + 5 * (3 + 4 * 6 + 4 * 5) + 2) * (4 + 8 * 2 * 9 * 7 + 6) + (6 * 4 * 6) * 5
+8 + (5 * 6 * 4 * 8) * (4 * 2 + (2 * 6) * (5 * 9 + 8 + 7 + 2) + 9) + (3 + (8 * 6) + 2 * (5 * 4 + 9 + 7 + 3 * 3) + 9) * 9
+(3 + 4) + 5 * 6 + 4 * 7 + (2 + 3 + (5 * 9 + 8 + 2) + 6)
+(8 + 5 + 2) + (7 + 3 + 6 + 6 * 9) + 3 * 5 + ((3 + 7 + 3 * 2 * 6) + 6 + 6)
+(2 * 6) + 6
+5 + (9 + 6 + 4 * 4 + 6 * (5 * 4 * 2 * 3)) * 8 * 6
+(2 + (4 * 5 * 2 + 4)) + 8 * 8 * 8 + 5
+7 * 5
+3 * 2 * 3 + (9 + 4 * 6) * ((3 * 4 + 9 * 5) * 2 + 5 * 6)
+(4 * 8 * (5 * 5) + (3 * 5 + 9 * 8 + 4 + 4)) * 5 + 4 * 6
+5 * 6 * (5 * 3 * 3) + 6 * 5
+(6 + 4 + (6 + 5 * 6 + 8 * 9 * 9) + 4) + 4 * 5 + 9 + 5
+4 + 2 * 4 * 2 * (5 * 4 + 9 * 8)
+2 + (6 + (9 * 4 * 6 + 8 + 4 + 3) * 6 + (3 * 8 + 6 + 2 * 4) + (4 * 4 * 2 * 8))
+8 + (2 + 5 * 6 * 7) + (5 * 3 * 6 * 5 + 8)
+7 * 6 * 9 * 8 + (2 + 7)
+(2 + 7 + (6 + 5 + 7 * 4 + 7)) + 4
+((7 * 5 + 8 + 2 + 7) + 9 * 2) + 3 + 8 + (9 + 7 + 8 * 6 * (5 + 3 * 5 + 6))
+8 * 5 + (8 + (7 + 4 * 9 + 2)) + 2 + (7 + 2) * 7
+9 + 4 * 9 + (9 * 6 + 2 * 6 + 5 + (4 * 9 * 6 * 7 + 5 + 8)) * (7 + 4 * 5 * (4 * 8 * 4 * 7) * 6) * 4
+3 * 5 + (2 * 9 + (2 * 5 * 5) * 5 + 8)
+3 * 9 * (8 + 6 + (9 + 2 + 2 + 8 + 4) * 6 + 7 * 3) * 2
+2 + 8 * 7 + (4 * 4 * 5) * 7 * 9
+5 + 9 * 6 * (4 + 9 + (8 * 7 * 9) + 9 * 9) + 6 + 8
+9 * 6 + 9 * (3 * 8 + (9 * 9 * 8 + 2 + 3 * 6) + 5 * 6) * 7
+4 + 6 + (2 + 2) + 7 * (9 + 3 * 5 * (3 + 3 + 8 + 3)) * 9
+3 * ((2 + 4) * 7 * (2 * 3 * 8 * 6 * 7) + 4 + 3) + 7
+9 + 3 + 4 * 8 * 5 + 9
+8 + (4 * 4 + (7 * 5 * 7 + 2) + (9 * 3)) * (2 * 9 * 9 * (6 + 7 * 8 + 9 + 6 + 3) + 3 * (3 * 9 + 7 + 6 + 5 + 8)) + 5 * (5 + (4 + 2 + 8) + (9 * 7 * 4) + 3) * 8
+(4 * 8 + 7 * 6 + 5 + 6) * (3 * 6 + 7 + (2 * 3 * 5)) + 4 * 4 * 5
+2 * 6 + 4 * 7
+6 + 8 * 7 * ((5 + 4 * 2 + 7 + 7 + 8) + 9 * 7 * 5) * 3 + (6 + 2)
+(6 + 3 * 8) * 4 * 3
+3 * 2 + 8 + (4 * (5 + 2 * 5 * 6) + 3 * 6)
+8 * (4 * 3 + 8 * 5) * 3 * 8 + 8
+5 * 4 + (3 + (2 + 6 * 8 + 3) * 4 * 3 * 6 + 4) + (8 + 6 + 2 * 3) * 4
+((5 + 8) * (6 * 6 + 4 * 8 + 7) + 7 * 3 + (9 * 5 + 9) * (7 * 9)) + 7 + 7 + ((9 + 7 * 4 + 9) + 3)
+(9 * 9 + 4) + (3 * 2 * 6 + 6 * 8)
+((3 * 6 + 9 * 9) + 6 * 4) * (9 + 6 + 9 * 2) * 8 * 8
+2 + 8 * (9 * 6 * 5) * 6 * 8 + 9
+(6 + 6 + 7) + 7
+8 + 7 * 9 + (9 + 5 + (5 * 5 + 2 * 9 * 8 * 6) + 6 + (4 + 6 * 8 * 2 + 2 + 9) + (5 + 8 + 9 + 4))
+3 + (7 + 9 * 2 + 6 * 6) * 2 + 5
+3 * 5 + 5 * 6 + (4 * 7 + 6 + 9 * 8 + 7) * 8
+5 + 5 + (5 * 8 + 5 * (4 + 5) + 4)
+(4 * (7 + 2 * 4 + 3 + 2 + 2)) * 2 + (4 + 3)
+(3 * 3 * 2 * 7 + 6 * (6 * 5 + 9 + 5)) * 4 + 3 * 7 * (4 + 2 * 2 + 8 + 7 * 4) + 7
+6 * 4 + 8 * 7 * (9 * 4 * 6 * (4 * 7 * 7 * 4) * (5 * 2 * 4))
+4 * 8 * (4 * 2 + 3 * 6) + (8 * 4) + 8
+9 + 5 + 3 + ((3 + 2) + 8 + 5 * 5 + 3) * 5
+4 * ((6 + 6 * 2 * 8) * 9 * (4 + 5 * 8) * 9 * 7 * 2) + 6
+6 * 5 * 2 * 2 * 7
+6 * 6 + (8 * 4 * 5) + 9
+3 * ((9 * 5 + 2 + 3 * 9 + 8) + 2 + (8 * 4 + 8 + 7 * 5) + 7) * 8 + 6
+4 + (2 + 7 + 7 + 2 * 7)
+2 + 3 + (2 + 5 + (3 + 4 + 7 + 5 * 9) * 3) * 8 * 5 * 9
+4 * ((8 + 9 * 4 + 2 * 9) * 9 + 6 * 4 + (3 * 9)) * 3 + 6 + 3
+4 + 4 * (5 * 2 + 6 + 6) + 6
+((5 + 6 * 7 * 2) + 7 * 7 + 9 + 7 * 8) + (9 * 5 + 4 * 5 * 7 * 8) * 3 * 2
+2 * 6 + 6 * (2 + 7 * 3 * 3 + 9 * 2) * 6
+(4 * 5 * 2 * 5 * 4) * 6 + (2 + 3) * 2 * 9 + (8 * 6 * 7 + 8)
+(3 * 6 + 3) + ((4 + 4 * 3) + 5 + 8 + 8) + 5
+8 * 4 + 3 + (8 * 2) + ((2 + 6 * 3 + 8) * 2 + 4) + 3
+5 * 7 * (6 * 5) * 8 + 9 * 9
+9 * (4 + 8 * 8) * (5 + 7 + 6 + (3 + 2 + 7 + 4)) * ((2 + 8) + 6 * (3 * 3 * 5) + 5)
+6 + (5 * (2 + 6 + 8 * 2 * 7 * 3) * (6 + 8) * 9 + 6)
+(9 * 7) * 2 * 6 + 2 + 4 + 6
+3 + 9 * 6 + 4 * (3 * 4) * 5
+(8 * 3) + (9 * (3 * 6 + 5) * 9 + 9) + (4 * 3 * 5) + 6
+6 + 3 * (4 + 2 * (2 * 5 + 7 * 2) * (2 + 2 + 5 + 2 * 7 + 7)) * 5 * 9 * 9
+9 * ((5 + 3 + 3 + 5) + 8 * 8 + (9 + 3 * 4 * 7 * 3 + 7) + 7 * 8) * 3 * 6 + 2 + 3
+6 * (7 + 9) + (2 * (7 * 3 + 5) * (6 * 5) * 7) * 6
+(5 * 8 + 7 * 5 + 5 * 6) * (3 * 6 + 8) * 8
+4 + ((5 * 6 * 5) * 9 * 2 * 3) * 4 * (2 + 9 + 3 + 6)
+(2 + 4 * 2 * 5 + 3) * 9 + ((5 * 8 + 9 * 2 + 3 * 6) + 4 * 4) + 6 + 4 + 7
+((2 + 4) * 3 * 3 + 4 + 3) + 8 * 3 + 4
+7 * (7 + 5 + 7) + 7 * 3 * (8 * 7 * 7)
+((9 + 8 * 6) + 3 * 2 * 5) * 2 * 4 * 9
+((3 * 2 + 2 + 3 + 9) + 8 * 3) * 9 + 8 + 3 + 4
+6 * 4 * 6 + 3 * (3 + 5 + (7 + 8 + 4 + 7 + 6) + 5 * 2 + 7)
+((5 + 5 * 2 + 3) * 7) + 6 + (8 * 3 * 9 + (3 * 9 * 5 + 7 * 4)) * 9 * 8 * 6
+(3 + 2 + 2 * 7 + 8 + 8) * (9 + 3) * 8 * 8
+9 * (9 + (2 + 6)) * 2 * 7
+6 * 4 + 2 * (9 + (6 * 2 * 7 * 6) * 7 + 8 + 3)
+5 * 9 + 8 + (9 * 3) + 9
+6 + ((5 * 6 + 6) + (4 * 3 + 3 + 4 * 5 + 4))
+4 + 6 + 7 * 7 * (2 * 7 * (9 * 4 * 9) + 2 * 5)
+(2 + 5) + 9 + 3 + 9
+((7 + 6) * 4 + 6) + 3 * (4 + 4 * 8 + 6 + (7 * 3 + 4 * 9) + (4 + 6)) + 3 * 9
+(2 + (8 * 8 + 9 * 8 * 6) * 2 * 3 * 2 + 6) + 6 * 5 * 8 * 6 + (7 * 9 + 6)
+2 + 4 * 8 + (9 * 9 + 3) + (2 * (4 + 4 * 7) * 3 + 6 * 9) * 5
+7 + 7 * 6 * 8
+8 * (7 + 4) + 7 * 8 * 5 + 3
+8 * 3 + (6 + 7 + 2 * 3 + 5) * 3
+(7 + 3 + (6 * 5 * 5 * 2 + 5 + 8)) * 8 + 2 + 8 + 5 + 3
+((5 * 9 + 6 * 2 * 7 * 6) * 7 * 5) + ((4 * 3) * 4 * 2 + (8 + 4 * 8 + 4) + (8 + 7 + 3 * 6)) * 6 + 8 + 9 * 5
+((9 * 3 * 3 * 6 + 4 * 3) + (7 * 5 * 9) * 7 * 7 + 2) * 9
+9 * 7 + 4 * (8 * 2 + 5 * (5 + 6) + 8 + 6) * 3 + 5
+((5 + 3) * 5 + 6 + 8 + 5 + 3) * 8 * 6 * 5 * (6 + 8 + 3 * 8)
+(4 * 3 * 7 + 6 * 6 + (4 * 5 + 6 + 5 + 8)) + 6 + 7 + 4 + 4 * 5
+((6 + 8 + 5 + 7 * 7 * 6) * (7 * 9 * 4 * 6)) + 5 * 4 * 9
+((9 * 2 * 7 * 7) * 7 * (4 + 9 * 9 * 2 + 6 * 5) + 4 + 2 * 8) + 9 * 7
+(4 * 5 + 7 + 3) + 8
+7 + 9 + 4 * 2 + 9
+(9 * (4 + 2 * 9 + 5 * 5 * 3)) * 2 * 5
+8 + ((6 * 3 + 4) * 4 + 4 * 9 + 3) * 9 * 6 + 4 + 6
+(6 * 4 * 8 + 7 * 5 + 4) * 8 + (5 * 4 * 2 * 3) * 5
+3 + 2 * (8 + 2 * 3 + 3 + (5 + 8 + 4 * 8 * 5)) * (4 * 6 + 8 + 9 * 8)
+2 + 7 + 3 * 6 * 8 * (6 + (3 * 4 * 5 + 4))
+(8 + 3 * 7 * (4 + 6 + 8 * 4 + 8 * 8)) + (9 * 9 * 2 * (3 + 4 * 4 * 8 + 3 + 8) + 6)
+((8 * 9 + 2 * 8) * 5 + 6 + 3 * 3) + 3 * 7
+4 + (2 + (6 * 5 * 3) * 2 + 2 * (3 + 7) * 9)
+(5 * 4 * (6 + 4 + 9 + 5) * 4) + 4 * 3 * 4 * ((9 * 6 + 9 + 8 * 8 + 6) * 2 * 7 * 4) * 2
+6 * 6 * (7 + 2 * (8 * 4 + 4)) + 7 * (9 * 6 * (5 + 6 + 2 + 2) + (9 * 4 * 5 * 5 * 5 + 6) * (6 * 6 * 5 * 6 + 8) + 5)
+5 * (4 + (7 + 7 * 9 + 5) * 5 * 9) * 3
+2 + (8 * 6 * 7 * 8 * 6 + 2) * 3
+4 * (9 * 3 * 9 + 3 + 9 * 8) + 3 + (9 + 8 + 4 * 8)
+4 * ((2 + 9 * 7 * 6 * 4 + 9) + 5 * 6 + 7)
+(5 + (2 + 3 * 4 + 7) + (4 + 6) + 6) + 9 * 7 + 5 * (7 + 5 * (8 * 7 * 3 + 2 * 4) + 4) + 7
+4 + 4 + (8 + 9 * (9 + 4 * 9 * 4 + 8 + 8) + 3 + 2 * 8)
+5 * (5 + 5 * 3 * 2 + 2 + 3) * (5 + 3 * 8 + 9 + 8 + 7) * 2
+8 + (3 * 9) + ((5 + 7 + 6 + 9) * 8 * 4 + (8 * 3 + 9 * 4 * 3)) + 4 * 4 * (3 + 3 * 7 * 6 * 2 + 7)
+6 * (6 * 4 * 3 * 2) + 8 * 9 * (2 + 5 + 6)
+4 + (8 + (3 + 2 + 6) * 5 + 2 * 7 + 9) + 5 + 4 + 3 * 4
+2 + 4 * ((5 * 4 * 2 + 8) + (5 + 4 + 6 + 9) + 7 * 2 + (4 * 4 + 3 * 6 + 3)) * 6
+((7 + 5 + 6 + 6 * 7) * 6 * 6 + (7 + 6 * 3 * 9) + 4 + 9) * 4 * 8 * 3
+8 * 3 + 7 + 2 * (8 + 7 + 5 + (9 * 4)) * 6
+8 + 3 + (3 + 5 * 6 + 5 + 6 + 3) + 3 * 9 + (2 + 6)
+5 * 4 * (4 * 5 * 6 * 5) + (8 + 7 * 3) + 6
+(5 + (7 + 4)) * 2 * (4 + 7 * (2 * 7 * 9) * (6 + 5 * 7 * 4) * 3 * 7) * (6 + 8) * 2 * (4 + (8 * 7 * 9) * 3 + (4 + 5 + 7 + 6 + 9))
+((2 + 2 + 5 + 8 * 7) + (9 + 6 + 4 + 7) + (7 + 3 + 7 * 7 * 2 * 6) * 6) + 8
+5 + (3 + 6) * 2 + (4 + (3 + 7) * 6 + 8 * 5 * 5) * (2 * 4 * 3) * 7
+(4 * 5 * 3 * 8 + 6) + 9 * 2
+(2 * 2 * 6 + (7 * 5 + 2 + 4 + 3) + 4) + 3
+9 + 4 + 4 + 6 + 4
+9 + 9 * 9
+6 + 6 + 4 + ((9 * 8) + 3 + 5 + 6 + 6 + 5) + (7 * 6 + 7 + 7 * 8) + (7 * 7 + 7 * 2)
+(2 * (4 + 2 * 4) * 7) + 5 * 8 * 7 * (5 * 3 * 5) * 6
+(5 + 5 + 5 + 3 + 2) + (9 * 9 + 3) * 6
+(5 + 2 + 2) * 5 * 7 * (9 + 6) * ((9 * 4 + 8) * 2)
+((9 * 8 + 9) * 6 + 6) * 6 + 7 * 7
+5 * (9 * 9 * 7 + 2 + 4) * 9 * 8 + 4 * ((4 * 5 + 9) + (9 * 6 + 9 * 8) * 4)
+4 * (7 + 7 + (4 + 6 + 4)) * (6 + 5 * 2 + 5 + 3 + 4)
+(4 * 5) + 4 * 4
+4 * 8 * 9 + 4 + 3 * ((9 * 6) * 6 + 3 * (8 * 8 + 2))
+3 * 7 + 7 * (5 + 5 * 8 * 9) * 7
+5 + (7 + 4) * 6 * 7
+7 * (2 + 2 + 5 + (6 * 6 + 5)) + 7 * 3 + (4 + (6 * 4) * 6 * 9) * 6
+6 * (6 + 9 + 4 * 7) * 8 * 9
+((3 * 6 + 8 + 5) * 9) * 7 + 6 * 8 + 2 * 3
+(8 + 9 + 5 + 9 + 5 * (2 + 6 * 3 * 5 + 8 + 8)) + 7 * 7 + (3 + 2 * 4 + 3) + 5
+7 + 7 * 6 + 9
+5 + (3 + 3 + 4 + (8 * 3 * 2)) + 6 * 5 + 8
+(3 * 6 + (2 + 2 + 9) * (3 * 2 + 2 * 3 * 8 * 6) + 5) + 3 + 2 + 4
+2 + 6 * ((4 * 8) + 3 + 4 + 4 * (5 * 6 * 4 * 6 * 4) + 9) * 7 * (9 + (6 * 2) + 8 + 8) + (3 + 2)
+8 + (2 + 6) * 3 + 4 + (7 * 4 * 9)
+9 + (7 + 4 + (4 * 9 * 2 + 7 + 7) * (9 + 2 + 7)) * 3 + 3 + 4 + 7
+9 * 5 + 5 + 5 * (2 + 7 + (3 * 2 * 4)) + 3
+9 + 4 + 2 + ((5 + 7 + 6 + 2) + 2) * 8
+7 + ((5 + 2 * 5) + 6 + 6 + 5 * (6 * 8) + 5) * 4 + 4
+4 + (3 + 5 * 4 + 8 * 3 * 4) * 8 * 4
+5 * (6 * 4 * 9 + 4 + (6 + 8 * 8 * 5)) + (6 * 9 + 2 + 6) * ((6 * 6 + 8 + 7) + 7 + 5 * 7)
+2 * 2 + 8 * 8 * 6 + (3 * 6 + (4 * 8 + 4 * 9 * 5 + 6))
+9 + (9 + 3 * 4 * 7 + 3 + 5) * (6 + 8 * 3 + 2) + 6 + 2
+9 + 5 + 7 * ((9 + 9 * 5 * 8 * 5 + 3) * 8 + (8 * 8 * 5) * 4 * 2) + 3 + 8
+9 * 2 + 8 * 7
+6 + (5 * 6 + (5 * 9 * 2 + 4 * 3 + 2) + 8) + (3 + 4 + 9 + 9 + 5) + 3 + 8
+(5 + 4 * (6 * 5 * 7 * 9 * 3) + 6 * 7 + 9) + 6 * 4 + 3 * 6 * 9
+(5 + 2 + 2 + 2 * 9 * 3) + 8 + 2
+3 + (8 + 6) * 7
+(8 + 9) + 6 + (2 + 4) * 5 + (5 + 6 * 8) * 3
+(6 * 2 + (4 + 2 * 2 + 3 * 9 + 8) * 8) + (7 + 5 + (4 * 5 + 7 * 7) + 2 * 8 + (4 + 6 * 6 * 2))
+(8 + 7 * 5 * 4 * 2) * 9 + 5 + 6 + 8
+3 * 7 * (6 * 8 + 6 * (3 * 2 * 4 + 9 * 3 * 3)) + 5
+8 * (6 + (5 * 6) * 8 * 3 + (2 + 9))
+(3 + 9 + 8 * 7) + 3 * 7 * (6 * (6 + 3) * 7 + (9 * 4) + 7 + 6)
+4 * 3 * (3 * 8 * 7 * 8 * 4 * (8 + 2)) * (7 * (4 * 4 * 5 * 7 + 4) + 6 + 4) + 8
+(2 + 3) * ((3 * 8) + 2 * 2 + 8 * 8) * (9 + 6) + 2
+4 * 6 + ((2 * 4 * 2 + 6 * 9) + 6) * 9
+9 * 8 * (2 * 7 + 6 * 7 + (8 + 8 * 4 + 9 * 7 + 6)) * 5 * (5 * (5 + 6 + 2) + (3 * 6 * 8 + 9 * 5))
+2 + 2 * (4 + 5 * (9 + 5 * 3 * 3) + 7 * 7 + 6) * 2
+2 + ((3 + 8 + 6 + 7) * 4 + 8 * 8 + 8) * (4 + 4 * 7 + 2 * 9 * 5) + 7
+8 * (7 + 6 * 7) * 2 * 5 + (9 + 5 + 9 + 9 * 6) + 9
+3 + (4 + (2 + 9 + 4 + 4 * 3 * 7) * (5 + 9 * 5 + 5)) + 2 * 7 * 4 + (2 * 4)
+4 * (2 * (2 + 5) * 9 + 5 + 5 * 3) * (2 * 4 + 4 * (3 + 6 + 2))
+6 + ((8 + 4) * 3 * 8)
+(9 * (8 + 3 * 2 * 9 * 7) + 9 + 5 + (8 * 8 + 8 * 5 * 3 * 4)) * (9 + 5 + 4 * 9) + 3
+2 * 8 + (8 * 4 + 2) * (5 * 5 + 6 + (6 * 4 * 4 * 4 * 3)) + 2
+7 * 4 * (7 * (3 * 4 + 3) + 8) + 9 + 2 * (6 + 7 + (5 + 4 * 2 + 4) * 6)
+5 + (9 * (5 * 7 + 6)) * 4 * 2
+6 + 7 * (8 + 6) * 8 * ((4 + 7 * 5 + 2 * 3) + (2 * 3 * 5 * 6 + 9)) + 9
+6 * (2 + 5 + (8 * 6 * 5 * 4 + 7 * 9) * 8 + 2) + 8 + 5 + 5
+2 + 7 + 8 + (3 + (5 * 6 + 6) + 9) * 3 + (7 * (7 + 6) * 9 * (4 + 5 + 3 + 3) + 4)
+7 * 8 + 2 + 3 + ((7 + 3 * 4 * 3 * 2 + 9) * (6 * 2) * 4 + 6 + 3) * 6
+3 + 4 + 5
+(4 + 4 * 3 * 2 * 6) + (9 * 3)
+3 + (9 * 8 * 2 + 7 * 6) + 7 + (3 + (3 * 4 * 2) + 3 * (2 + 3 * 4 * 5 * 4 * 6) * 2) * (6 + 4 * 9) + 5
+7 + (7 * 4 * (9 + 8 + 2 + 2 * 5) + 2 * (4 * 3 + 7 * 8) * 9) * (3 * 9 * 2 * (7 * 8 * 4 + 8 + 5 * 6)) * 3
+((6 + 4 + 5 * 5) * 5 * 2 + (2 + 2) + 9 + (4 * 3 + 9)) + 7
+2 + 2 * 4 + (4 * 9 * 7 * (9 * 8 * 6 * 7))
+6 + 4
+7 + (3 * 4 + 2) * 8 + 7 * 4
+7 + 4 + 8 + (9 + 7 * 4 * 8 * 4) + 4 * 8
+5 + 8 * 3 * ((8 * 9) * 2 + 6 * (2 + 5 * 8 + 3 * 9) * 4) + 9 + 8
+8 + 6 + 6
+6 * 6 * 6
+6 + 9 + 5 * ((3 * 8 + 6) + 8 * 7 + 3 + 7 + 6) + 2
+4 * 9 + 3 + 8 * ((2 + 2) * 5 * 3)
+6 * (4 + 7 + 4) * 5 * 7 * 7 + 6
+6 + 7 + (6 + 6) * (3 * (8 * 8 * 4 * 4 + 3 * 9) + 2 + 5 + 8) + 5 * 6
+8 * 8 + (9 * 9 * (2 * 3) + 2 + 6) * (5 * (4 + 9 * 5 + 2 + 4 + 7))
+9 + 5 + 7 * (4 * (4 + 4 * 4 + 7 * 7) * 9 + 6 * 5 * 3) * 5 * 9
+(6 + 8 + 4 + 8) + 6 + 9 + ((6 + 4 * 9 * 9) + (6 * 6 + 7 + 9 * 2) * 7) * 5 * 9
+8 + ((7 * 8) + 5 + 6) * 4 * 7 * 9
+(6 + 2 + 2 * 3 * (8 * 6) * (5 * 9 * 6)) + 9 * (4 + 3 + (5 * 2) * 2 + 3 + 6)
+4 * 8 + 7 * ((5 + 4 * 6) + 5 + 3) + 3 + 4
+3 + (6 * (8 + 8) * 9) * 4 + 4 * (5 * (9 * 3 * 7 * 4) * (4 + 6 * 8 * 8 * 4) * 8) * 3
+7 * 3 * 4 * 5 * 7 + (3 + 7 + (3 * 5 * 3 * 3 + 3) + 6)
+(5 + 5 * 4 + 5 + 7) + (8 + 7 + 8 + 2 + 3)
+(9 + 8 + 8 + 3 * 2 + 5) + 4 + (8 * 5 + 3 + 9 * 8) + (7 * 4) + 5 * 2
+(5 * 9 * 2 * 9) + 5 * 8 + 4
+9 * 3 * 9 + (9 + 3 + 2)
+4 * 5 * 7 + (7 * 6) + 6 + 9
+(3 + 8) + 4 + (7 + 2 * 9) * 7 * 8 + 4
+8 + 3 + 4 + 6 * ((6 + 7 * 4 + 6) + 6 + 3 + 9 * 6)
+(4 * 8) * (9 + (2 + 4 * 6 + 4 + 8)) * 3 + 9 * 4 + 8
+5 * 4 + (9 + (2 * 8)) + 9 * 2
+9 * 2 + (3 * 2 + 5 + (3 * 8 + 5 * 2 * 5 + 6) * 5 + 8) * 7 * 2
+8 + (3 * 5 + 2 * 7 + 8 * 2)
+5 + (4 * 7 + 2) + (5 + 8 * 5 + (4 * 9) + (3 + 3))
+((4 * 5 * 8 + 6 + 8) * 9 * 3 + 4) * 8 + 9 * 7
+((6 * 6 + 5 * 4 + 2 + 4) * 7 + 5 + 9 * 8) * 5 + 9
+5 + (9 + 5 * 9 + 6 * 3) * ((3 * 6) * 2 + 8) + 3
+((6 + 5) * 5 * 6 * 9 * 8) + 3 * 7
+(8 * 6 + (5 + 5) + 4) * 7 + 3 + 8
+4 + (2 * 3 * 8 + 3 + 3) * 8
+2 * (7 + 6 + 2 + 3) * 8 + 2 + 2 * (4 * 3 * 5 * 8)
+6 * (8 + (3 * 6 + 8 + 8 + 6) * 9)
+((8 * 3 + 2) * 6 * 2 * (5 + 6 * 2 * 8)) + 8
+6 + (6 * 5 + (5 * 9) * (6 * 5 + 8 * 2 + 5)) * (8 * (3 * 3 * 5) + 9) * 7
+(7 + 6 + 2 * 5) + 2 + 6
+(8 * 7 * (6 * 4 + 6 * 3) * 6) + 4 * 5 * (5 * (2 * 2 * 9) * 4 + (2 * 6 * 5) + 9 + 9)
+((3 * 2) + 7 + 6 + 4 * 9) + 4 + 2 + 7 + (4 * (7 * 9 * 2) * 3)
+(3 * (5 * 9 + 9 + 9 * 9)) + (9 + (4 * 4 * 6) * 9) + 9 * 7 + 4 * 9
+4 + (6 * 6) * (9 * 8) * 9 + (6 + 7 * 5 + (2 + 9))
+(8 + (5 + 7)) + 7 * 8 * 9 + 9
+8 + 4 + 6 * (5 * 3 + 8 + 7) * 6 * 3
+3 + 9 + 6 + (2 + 8 + (8 + 5 * 5) * 4 + 4 * 8) * 9 * 3
+(4 + 4 * 3 + 4) * 8 * 4 + 4 + 6
+2 * (3 * 6) + (4 + 3 * 8 + 5 + (6 * 5 * 2 + 5 + 2 * 9))
+4 * 3 + (7 + 7 * 3 * 5 * 4 * 4) + (8 + 5 * 8) * (2 * 4) + 8
+(4 * 9 * 6 + 6) * (6 * (8 + 4 * 9)) + 6 + ((4 + 2 * 9) * (3 + 3 + 6 + 3) + 9 * 9 + 8 * 7)
+2 * 5 + 5 * (8 + 4 * 3 + (7 + 6) * 7 + 3) * 8
+((3 * 4 + 4 * 9) * 6 + 7 * 4 + 7 * 2) * 7 * (7 + 9 + 6 * 8) + (3 * (6 * 6 * 9 * 7 + 4) * 5 * 2 + 3 + 4) * 8
+(5 + 6 + 9 + 3 * 3 + (2 + 8 + 5 + 3)) + (2 * 5 + 6 * 9 * 6) * 2 + 9 * ((5 * 9) + 8 * 8 * (7 * 4 * 3 * 4 * 4 * 7))
+2 + 8 + 4 + 7 * ((8 + 7 + 8 * 3) + 9 * 2 + 6 + 3) + 6
+4 * (8 * 8 * 4) * 9 + (7 + 7 + 2 * 2) * 6 + 8
+3 + (6 * 4 * 6 + 3 * 9 + 3) * 7 + 3 + 4
+3 * 4
+(4 * 6 * 4) + 3 + 7 + 6 * 9 + 7
+3 * (6 + 8 * 4 * 2) + 5 + 5 * (4 + 6 + 2 + 6)
+(5 + 2 + 4 * 2 * 2) + (5 + 5 * 5 * 3) + 3 * (4 + 9 + 6 * 6 + 2)
+((6 + 9) * 6 + (3 + 7 * 4 + 2 + 5 * 6) + 3 + 5 * 2) * (2 * (5 * 9 + 9) * 5) + 8
+9 * 8 * 9 * 8
+6 * 8 * 4 * 4 + 4 * 4
+((8 * 7 * 6 * 3) + 7 * 2 * 6 * (4 + 6 * 5 * 9 * 5) * 8) * (3 * (4 * 6 + 8 + 2 + 6 * 2) + (2 * 4 + 4 * 7 + 3 * 5) * 9 + 9 + 8)
+(3 * 5 * 7 * 4 + (4 + 6 + 6 + 9 * 6 * 3) * 5) * 6
+(4 * 4 * 5 * 8 * (3 + 4) + 7) + 6 + 4 + (8 + 3)
+9 * 7 + 8 + 2 * 3 * (3 + (2 * 3 * 7 * 5 * 9) + 8 * 9 * 5)
+((3 * 6) + 3 + 9) + 7 * 8 * 3 * 9
+8 * 4 * (6 * 9) * 3
+9 + ((5 + 3 + 4 * 3 * 9 * 6) * 6 + 9 + 3 + 8 * (5 + 4 + 7)) + 9 * 4
+(4 + 6 * 3 + 2 * 9) * (6 * 9 * 4 + 7) + 8 + 8 + 6
+(5 * 3 * 6 * 3) * 7 * (5 + 6 * 6 * 5)
+4 * 6 * 8 + ((4 + 7 + 6) * 4 + (4 * 7)) * 8
+6 + ((4 * 9 + 6 + 5 * 5 * 7) * 5 * 3) + 7
+(8 * 4 + 8 + 9 * 9) + (5 * 6 + 3 + 6 * (9 + 8 * 7 * 6 * 8 + 6) + 5) * 9 + (6 + 6 * 2 + 2 * 4 + 8) * 5 * (8 + 5 + 2 + 3)
+(8 * 2 + (7 * 9) + 8) + 3
+2 + 9 * 6 + 5 * (3 * 7 + 8) + 3
+((9 * 2 * 5) + (9 + 8 + 8 * 9) * 7 * 7 + 9) + 2 + 8 + 3 + (5 + 7)
+5 + 9 + 5 * 4 + 3 + 5
+4 + 9 * (6 * (7 + 7 + 9 * 3) * 5 + 3 * 3)
+2 + 8 + 6 * 8 * (4 + (9 * 8) * 2) + 2
+3 + 7
+8 + 7 + 8 * (5 + 7 * 9 * 9 * 8)
+6 + (3 + (5 * 3) + (9 + 6 * 9) * 4 + 8)
+7 * 2 + (5 * 6 + 2 + 6 * 3 + (9 + 7 + 7 * 8 + 9 * 7)) * 8 * 7 * 7
+(6 + 3 * 5 * 6) + (2 * 2 * 5) + 8 * 3 * 3 + 5
+(2 * 8 + 6 * (6 + 3 * 2 + 7 * 7 + 6) * 5 + 5) * 3
+(6 * 9 + (5 + 9 * 8) + 2 * (6 * 8 * 8 + 6 + 3) * 7) * (7 + 3 * 5)
+4 * 2 + 8 * 9 + 3
+8 * ((5 * 2 * 5 + 9 + 4) * 4 * 2) * 8 + (3 + 2 + 3 * 7 * 8 + 5) + 4
+9 * 9 * 5
+3 * 2 * 8 * (6 + 5 * 9 + 6)

From 0967ca880025f8ef1a18117f5b56a1d44ac0285d Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Sat, 19 Dec 2020 00:39:13 -0800
Subject: [PATCH 10/12] Completed day 19

---
 2020/days/day19.cpp     | 195 +++++++++++++
 2020/inputs/day19.input | 587 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 782 insertions(+)
 create mode 100644 2020/days/day19.cpp
 create mode 100644 2020/inputs/day19.input

diff --git a/2020/days/day19.cpp b/2020/days/day19.cpp
new file mode 100644
index 0000000..9f3ed8c
--- /dev/null
+++ b/2020/days/day19.cpp
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <unordered_map>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+enum RuleType { Char, Sequence, Alternator };
+
+struct Rule {
+	RuleType type;
+	char c;
+	std::vector<u64> list;
+	std::vector<std::vector<u64>> or_list;
+
+	explicit Rule(char c) noexcept : type(Char), c(c) {}
+	explicit Rule(std::vector<u64> && list) noexcept : type(Sequence), list(std::move(list)) {}
+	explicit Rule(std::vector<std::vector<u64>> && or_list) noexcept : type(Alternator), or_list(std::move(or_list)) {}
+};
+
+auto extract_numbers(const std::string & list) -> std::vector<u64> {
+	auto nums  = std::vector<u64>();
+	auto end   = usize(0);
+	auto start = usize(0);
+	while ((end = list.find(" ", ++end)) != std::string::npos) {
+		nums.push_back(std::stoll(list.substr(start, end - start)));
+		start = end + 1;
+	}
+	return std::move(nums);
+}
+
+auto matches(const std::string & string, usize & index, std::unordered_map<u64, Rule> & rules, u64 rule_id, bool sub) -> bool;
+
+auto matches_list(const std::string & string, usize & index, std::unordered_map<u64, Rule> & rules, const std::vector<u64> & rule_ids, bool sub) -> bool {
+	auto local_index = index;
+	for (auto i = usize(0); i < rule_ids.size(); ++i) {
+		if (!matches(string, local_index, rules, rule_ids[i], true)) {
+			return false;
+		}
+	}
+	index = local_index;
+	return (sub || index == string.size());
+}
+
+auto matches(const std::string & string, usize & index, std::unordered_map<u64, Rule> & rules, u64 rule_id, bool sub) -> bool {
+	if (index >= string.size()) {
+		return false;
+	}
+	auto & rule = rules.find(rule_id)->second;
+	switch (rule.type) {
+		case Char: {
+			if (string[index] == rule.c) {
+				++index;
+				return (sub || index == string.size());
+			} else {
+				return false;
+			}
+		}
+		case Sequence: {
+			return matches_list(string, index, rules, rule.list, sub);
+		}
+		case Alternator: {
+			for (auto i = usize(0); i < rule.or_list.size(); ++i) {
+				auto local_index = index;
+				if (matches_list(string, local_index, rules, rule.or_list[i], sub)) {
+					index = local_index;
+					return true;
+				}
+			}
+			return false;
+		}
+	}
+	// むだ!makes the compiler happy though
+	return false;
+}
+
+auto min_length(std::unordered_map<u64, Rule> & rules, u64 rule_id) -> usize;
+
+auto min_length_list(std::unordered_map<u64, Rule> & rules, const std::vector<u64> & rule_ids) -> usize {
+	auto len = usize(0);
+	for (auto i = usize(0); i < rule_ids.size(); ++i) {
+		len += min_length(rules, rule_ids[i]);
+	}
+	return len;
+}
+
+auto min_length(std::unordered_map<u64, Rule> & rules, u64 rule_id) -> usize {
+	auto & rule = rules.find(rule_id)->second;
+	switch (rule.type) {
+		case Char:     return 1;
+		case Sequence: return min_length_list(rules, rule.list);
+		case Alternator: {
+			auto min = min_length_list(rules, rule.or_list[0]);
+			for (auto i = usize(1); i < rule.or_list.size(); ++i) {
+				auto len = min_length_list(rules, rule.or_list[i]);
+				if (len < min) {
+					min = len;
+				}
+			}
+			return min;
+		}
+	}
+	// このもむだ!
+	return 0;
+}
+
+auto day19() -> void {
+	auto rules   = std::unordered_map<u64, Rule>();
+	auto strings = std::vector<std::string>();
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day19.input");
+		getline(file, line);
+		while (line != "") {
+			auto end = line.find(":");
+			auto id = std::stoll(line.substr(0, end));
+			if ((end = line.find("\"")) != std::string::npos) {
+				rules.insert_or_assign(id, Rule(line[end + 1]));
+			} else if (line.find("|") != std::string::npos) {
+				end = line.find(":") + 2;
+				line = line.substr(end, line.size() - end) + " |";
+				auto sequences = std::vector<std::vector<u64>>();
+				end = usize(0);
+				auto start = usize(0);
+				while ((end = line.find("|", ++end)) != std::string::npos) {
+					sequences.push_back(extract_numbers(line.substr(start, end - start)));
+					start = end + 2;
+				}
+				rules.insert_or_assign(id, Rule(std::move(sequences)));
+			} else {
+				end = line.find(":") + 2;
+				rules.insert_or_assign(id, Rule(extract_numbers(line.substr(end, line.size() - end) + ' ')));
+			}
+			getline(file, line);
+		}
+		while (getline(file, line)) {
+			strings.push_back(std::move(line));
+		}
+	}
+
+	auto successful = usize(0);
+	for (auto i = usize(0); i < strings.size(); ++i) {
+		auto index = usize(0);
+		successful += matches(strings[i], index, rules, 0, false);
+	}
+	print(successful);
+	
+	successful = usize(0);
+	auto min_length42 = min_length(rules, 42);
+	auto min_length31 = min_length(rules, 31);
+	for (auto i = usize(0); i < strings.size(); ++i) {
+		auto unsuccessful = true;
+		auto base = min_length42 * 2 + min_length31;
+		auto list = std::vector<u64>{ 42, 42, 31 };
+		for (auto j = usize(0); unsuccessful && j * min_length42 + base <= strings[i].size(); ++j) {
+			auto copy = list;
+			for (auto k = usize(0); unsuccessful && k <= j; ++k) {
+				auto index = usize(0);
+				unsuccessful = !matches_list(strings[i], index, rules, copy, false);
+				copy.push_back(31);
+			}
+			list.insert(list.begin(), 42);
+		}
+		successful += !unsuccessful;
+	}
+	print(successful);
+}
diff --git a/2020/inputs/day19.input b/2020/inputs/day19.input
new file mode 100644
index 0000000..bb765f9
--- /dev/null
+++ b/2020/inputs/day19.input
@@ -0,0 +1,587 @@
+27: 116 44 | 127 69
+19: 60 116 | 55 127
+91: 127 13 | 116 127
+11: 42 31
+30: 80 116 | 100 127
+53: 78 116 | 100 127
+47: 116 129 | 127 76
+21: 57 127 | 100 116
+26: 86 116 | 28 127
+86: 127 122 | 116 29
+74: 127 39 | 116 105
+41: 118 116 | 132 127
+13: 116 | 127
+115: 82 116 | 72 127
+100: 116 116 | 116 127
+5: 78 127 | 91 116
+31: 101 127 | 121 116
+134: 116 117
+73: 123 116 | 62 127
+69: 116 124 | 127 77
+28: 71 116 | 66 127
+14: 131 116 | 128 127
+111: 127 59 | 116 117
+6: 127 53 | 116 79
+104: 26 116 | 65 127
+61: 78 127 | 56 116
+67: 127 30 | 116 130
+32: 81 127 | 27 116
+2: 116 117 | 127 72
+128: 57 116 | 91 127
+81: 127 96 | 116 51
+38: 127 59 | 116 54
+36: 22 127 | 107 116
+35: 116 61 | 127 24
+7: 116 100
+18: 16 116 | 82 127
+116: "a"
+54: 116 116 | 127 116
+84: 20 116 | 93 127
+92: 38 127 | 111 116
+64: 127 57 | 116 82
+105: 116 43 | 127 110
+44: 127 106 | 116 88
+93: 33 116 | 56 127
+82: 116 13 | 127 116
+75: 2 127 | 9 116
+65: 127 97 | 116 36
+4: 5 127 | 98 116
+1: 114 127 | 58 116
+122: 54 127 | 59 116
+70: 116 67 | 127 75
+117: 127 127
+68: 48 127 | 40 116
+97: 127 95 | 116 113
+132: 127 33 | 116 54
+51: 23 127 | 30 116
+119: 127 37 | 116 103
+63: 57 127 | 59 116
+34: 57 13
+48: 116 73 | 127 47
+23: 82 127 | 59 116
+66: 127 82 | 116 78
+95: 127 100 | 116 82
+123: 117 116 | 82 127
+24: 116 33
+120: 49 127 | 99 116
+103: 127 90 | 116 83
+102: 72 13
+58: 46 116 | 45 127
+106: 56 127 | 117 116
+85: 126 127 | 133 116
+3: 74 116 | 85 127
+20: 33 127 | 56 116
+127: "b"
+45: 116 102 | 127 18
+126: 127 41 | 116 112
+94: 116 87 | 127 21
+114: 35 116 | 19 127
+0: 8 11
+99: 127 34 | 116 76
+80: 116 127 | 127 116
+50: 15 116 | 7 127
+55: 127 91 | 116 59
+90: 92 127 | 94 116
+25: 57 116 | 54 127
+124: 116 57 | 127 91
+77: 78 116 | 78 127
+56: 127 127 | 116 116
+79: 116 59 | 127 57
+12: 127 64 | 116 115
+130: 17 127 | 33 116
+8: 42
+60: 116 72 | 127 59
+113: 117 127 | 117 116
+131: 16 127 | 56 116
+46: 134 116 | 62 127
+83: 6 127 | 50 116
+33: 116 116
+88: 116 57 | 127 54
+118: 116 100 | 127 54
+125: 100 116
+121: 32 116 | 104 127
+29: 127 17 | 116 57
+101: 127 1 | 116 68
+22: 116 117 | 127 100
+43: 127 125 | 116 22
+10: 29 127 | 63 116
+112: 98 116 | 107 127
+87: 80 127 | 57 116
+129: 54 116 | 17 127
+98: 116 80 | 127 117
+57: 116 116 | 127 13
+107: 127 72 | 116 59
+40: 116 14 | 127 4
+39: 12 116 | 84 127
+133: 116 108 | 127 10
+71: 127 56 | 116 54
+76: 116 78 | 127 33
+15: 127 59 | 116 78
+42: 119 116 | 3 127
+9: 127 72 | 116 100
+72: 127 127 | 127 116
+17: 13 13
+16: 116 116 | 13 127
+49: 53 127 | 25 116
+62: 127 80 | 116 100
+52: 72 116 | 33 127
+37: 70 127 | 120 116
+110: 89 127 | 87 116
+96: 116 52 | 127 55
+78: 116 127
+108: 127 109 | 116 71
+109: 116 59 | 127 16
+59: 116 127 | 127 127
+89: 57 127 | 33 116
+
+babababababababaabbbbbabaaabbabbabbabbaa
+abbbbbaababbbabbbbbaaaaaaaababbbaabbabab
+bbaaaaababababbaaaaabbababbabaabaaaaaaabaaaaaaaa
+aabaabbaaaaaabaaaaaaabaabaabbbbb
+bbaababbaaabaabaababbaaaabaababbaabbbaababbaaabababaabab
+bbabbabbabaabbaabbbbaabbbbaabbaa
+baaaabbbabaaababbababbbbababbbbbaaaabaabaabbbbaa
+aaaabbabbaaaabbbaabaaabbaaabbbbababaabab
+bbbaabaabbaabaaaaaababbbbaaaabbaaabaaabbbbbbbbbbbababbab
+aabaabbaaabaaaabbbbaababbaabababaabbbbab
+bbaabbbbbaaabbbbbabbbbaaaabaabbaabbaabbabbababbb
+aaabaabaabaaababbabbabbb
+abbababbabbababbaaaaaaab
+ababbaaaabbabbabaaaabbaaaabaaabbbaabbbbaabbbabbbbbbaabbabbabbaaaababaabaabbabbaa
+abbababaabbbabbbaaababbbabaaababbaababaabaaaaaaaaabababbabababab
+baabbbbabaababbabaababbbababbbaa
+aaabaabbbbbbaaaabaaaaabaaaaaabaaaababbaaaaaabaab
+babababbabaaabbabbbbbbbabaaaabbaabababaaaabbbaab
+aabaabbaabbabaababaaaaaabbbababaaabbbbab
+aabaaabbbaabaabbabaaabbabbababaabbbbabbb
+abababbaaaabbababaaaaabaaaaaabbaabbbaabb
+bbaaabbbbaababaabbbaabbbabbbababbbbabbaa
+babaaaaabbbbbbabbabaaaba
+baaababbaabbbabbaaaababbababbabbbbbbbbbbaabbbaaaaaababbbbbaabbbb
+bbbbaaabbaaaabaabbbbbbbabaaababaabbbbaaa
+bbabbabbbbabaabbaaaaabab
+baaababbbbbbaababaabaabbbbbbaaaaaaaaababaabbbaabaabaaaba
+baababaaaababaaaaaaabbbaabbbbbaabaaababaaabbabaaaaabbaaa
+abbbbbbbaaabaababaaabbaa
+bbbabaaaabbabbbaaaaabaaabbbaabaabbbaaabbbabaaaba
+abaabbaabaaabbabaaaaaaaa
+aaabaabbaabaaaabaaaabbaabbabbaab
+bbaabaaaabbaabaaababaabb
+bbabaaababbaaabbbbabbabbabaaaaabbaaaabbbabbababbabbbbaaa
+abbaaabbababbabbbaaaabbababaabab
+aabababababbbaabaaabababababaaaaaaabbaaabbabaaba
+abaaaaabbbbbbaabbaaaabababaaaabb
+bbbbabbabababbbbaaaaaaba
+aaaaaabbbaabbbababbabbbabaaabbbbabbabbaa
+bbbababbbababbbbbbbbbabaabbaabaababbaaaabbababbb
+abbabbabaaaabaaabaaabbbaabbaabababbbaabaaaaaaaabbaaababa
+abbbabbbabaababbaababaabbabababbaaaaabaababaabaabaabbabbbabbbbbb
+bbbaabbbbbbababbaaabbabaabbbbababbaababbabbabaaababaabbb
+bbaaaaababbaaaaaabababaaaababbbabaabababbabbbaaa
+aabbbabbbbabaabbabbaabba
+ababbababbbbaaaabbabbaab
+abbaaaababbbbbabbaaabaaabbabbabbbabababbabaabbba
+bababaabbbaabaabbaaabbaa
+bbbaaaabbababaabbbababab
+babaabbbbaaababaababaaabbbaabbab
+bbbabaaabaaaababbaabaaabbababbbbbaabbaab
+abbbbbbbaababaabaabababb
+abbbabaabababababbaaaaabaaabbabb
+baaabbabbbbaababbbaabbba
+bbbbaabababaabbabaabbbaaaababbab
+abbaaaaaaabaaabbbaaabbababbaaaaa
+aaaabbabaababbababbbbaababbbbaaa
+abbbbbbbbbbaaabbbabbabbb
+abaaababbababbbbbabaaaabbabbaabbaaaababb
+bbaabbbabbbabbbbabaabbbb
+babbaababbbbbbabaababaaabbaabaababaaaaba
+bbbaaaabbbbbaaabbaabbaba
+ababbaaabbbbbaabbbaabbbbbaabbbbb
+baabbbabbaababbbbbbabbbb
+abbaabaaaaaabbabbaaabbabababbaaaababbbbbaaaababb
+bbbbbaabbbbaaabbbbabaaba
+bababbaaaababaaabbbabbba
+bbbbaabbaababaabababbbaa
+bbbaaaaaabaabbabaabaabaa
+bbbaaabbbbabbabbaababbbb
+aabababababbaabaabbaaaaaabbabbabaabbabab
+babbbabbaaababbbbbabaabbabaaaabb
+aababaaabbbbbaaabaabbabb
+bbbbbaaabaaabbababbaaaaaabaabaaa
+bbaaaaaababaaabbaabbaaaa
+baababbbaaaabbaaabaabbba
+aababaaaabababaaaaaabbabababbbbb
+bbaababaabbababbbbbbbaaaabbbaabbabbbaaaa
+bababbbbaababaaabaabbbbb
+bbaaaaaababaaaababababaaabaabbba
+bbbaaaaaabbaabaaabbaabaaabbabaaababbbabaaabbaaababaaabbb
+aabbbbbbbbbaaaaaaabbabbb
+bbabaababbbaabaabaaaabbaabbabbbbbabaabbabbbababaaababbababbabbbabbabbbbabbabbbababbabbaababbaaaa
+abaaababbabbbaabbabaabbaabaaabbaabbbaaabbaabbaabbbaaaabb
+aabaabbbbbbaababbabbaababbbbbbaa
+baabaaabbbbbbaaaabbbbbabaabbbaba
+bbbbbbbabbaababbabababab
+aaabaaabbbbbbababaaababbbbbbbbabaaababababbbbaaaabaababaaabaabababbaabba
+abababaabbaabbbbaabbaaaa
+bababbbbbbbbbaabbaaabbaa
+abbbbbbaaabbbaaaaabbabab
+baaaababbbbaaabbaaaaaabbababaabb
+abbbbbabbbabaabbbabbaabb
+aababbbabbbbaabbaababbaa
+bbbbaabbbbaaaabaaabbabaa
+abbaaaabbbaaabaabbbababbbbbbbbbabbbaababbaababbabababbabbbbabbbabbaaabba
+aaabbabaababaaaaabababbaabbababbbbbbbababbbbbabb
+abbbbbababbbaaabaabbaaba
+abbbbbbaaabbaaabaabbbbbaaabbaababaaaaaaa
+ababaaaaaaababbbaaabaaaa
+babbbbaaabaaababbbbbbbaa
+abaaaaabbabaaaabbbbbbbaa
+bbbaaaabbbbbabbababbbbbb
+baabbaaaabaabbaabbbbbbaaabaaabababbbbabaabbbabbaaaababbaaaababbaaabbaaababbbbaba
+bababbbabaaababbbabbbbaaaaaabbbaabbabaab
+bbbbaabbbababbbbabbbabbbaabbbbba
+aaabbbbaabbbaaabaababbaa
+aaabbabababbbabbbbbbabbb
+ababaaabbbababaabbbbbbbbbabaaabbabbbbbbbababaabb
+abbbaaababbbbabaabbaaaaabbbabbaaaaabbabb
+baabbbababbabaaabbbbbaaaaaabaabaabaaabbababbaaab
+aabaabbabababbbbbbbababbbbabbbabbbaaabba
+baaababbbbbaabaabaabbaba
+abbbbabaabbbaaabbaabbbabbbbbaaabbbababab
+babaaabbabaabbababaaabaa
+abaaabbabaaaaaababaaabababaaaaabaabababb
+abbbabbbaaababbbababaaaabbabababbbaabbab
+aaaaabaaabbbbbbbbaaabbbaabbbbbbabbaabbabaaabbaab
+bbbbbbbabbbaaabbaaabaabaababbabaabaaabaaabaaabbb
+abbbbbbaabbabbbabbbbabbabbbbabbaaaaababb
+bbbbbaaababbbaabaabbbbbbbbbbbbbbbababaaa
+abbbbbbbbbbbbaabaabbaaba
+abbaaaababbbbbaaabbabbbaaabaabbabbbbbbbababaabaa
+abaaabababbbbabaabbaabbaaabababaaabbbabbabbababaabbbaaaaabaabbaaaaaaabba
+bbaaabbbaabaaabbbbbaaaaababbabab
+baaabaaabaababbabbabaaabaaabbabb
+bbbbabbaabababaaabbbaaba
+aabbbabbbaabbbbaaaabaaab
+abaaabbabbaabaabaababababbabaaabbbbbbabbabbbbbbbbbbbbbbbababbbaabbabbaababbaaaba
+bbbaabbbabbbaaabbbbbbabaabaaaaba
+abbbbabababbbaabaaaababa
+abbabbbaabbbbbbbaaabaabbbbbbaabaaabbabaabaabbbbb
+babbbabbbbbaaabbabbaaaaaabbaaaabbbbbbbbb
+bbbbaaaaabbabababbaaabbaabaaabbaababababbbbabbbabbaaaabaabbaabaaabbababb
+abbabbbabaabbbabaaabbaab
+bbaababbbaababaaaabaabab
+bbbbababaaabababbbabbbbbbabababaabbaabaababbaaab
+baaaababaaaaabbaaaabbbbbbbaaaaabbabbababaaaabbbb
+baaaaaabbbaaaaabaaabbaabbabbbaaababbabba
+abbbbabababbaabaababbbab
+aaabaabaaaabaaabbbbababbaabbaaaabbbabbaa
+aaaaaabbbbaaabaaaaaaabaabbbabababaabbaaa
+abbbbbbbabbbbabaaabbabaa
+bbaaaaabbaababbabbbaabba
+abbbbababaaababbbbbbabab
+abbababbababbbabaabbaabbaaaaaaaaaaabaaaa
+bababbbbbbaaaaaaabbbabba
+baaabbabbbbbabbabaabbaababbbaaaa
+baabaaababbbaaabbaabaaabaababbbbababaaba
+aaaabbaabbbaabbbbaabaabbbaabbaaa
+baaabaaaabbbbbabaaabaababaabababbaaababa
+abbabbabbaaaaaabbaaaabaababaaaababbbaabb
+bbaaaaaaaababbbaaabaaaabbaaaabaababaabaa
+baaaaaabaaaabbbaaabbaaba
+aababababbbbbaaababababbbbaaaaaabbaaabba
+bbbaaabbbabababbbababbaaaaabbaaa
+baababaabababaabbbaaaabb
+bbaababbaababbbaaababbbb
+aaaaaabbaabbbbbbbbaaaaabbaaaababbbbababbbbaaaababababaaaabbbbaab
+baaabbabababbabababaabbaabbaabaaabaababbbbabaaabbabbbaaaaaababbabbabbbabaabbbaab
+abbbaaabbababbbbabbbabba
+aababaababbbbbbbabbababbbbbbbaba
+abbbabbbbabaaabbbbaabbbbababbaaaaabababaabbaababbbbbbbaababbaabbbbbbbbaaabababbb
+bbbaaaaaaababbabbbbbabaabaabbbabaabbbbbbbababbbb
+baababbabaaabaaababaaabbbaabaabbbbbaaabbbabbabaaababaaba
+aaabaaababbaaaaaaaabababbabaaaba
+abaaababaabaaaabaaaabbbb
+bbbaabaababbaababaaaaabaaaabaababbababab
+bbbbbabaabbaaaaabaaaaabaabaabaab
+baaaabaaabbabaabbbbbbbbb
+bbaaaababbbbbbabbaababbaabababbabbbbaaaaabbbbbaababaabaabbbaaabaaaaababbababbbaaaaababba
+bbbababbababbabbbabbbaabaabaaabbbababaabaabbaaaa
+bbbbaabaaaaabbabbababbab
+baabaaabbabaaaaababaaaba
+abbbabaabaabbbbaabaababa
+abbbbbaabbbbbbabbbbbaabbbaaababbabbabaaaaabababb
+bbbbaaabaaababbbaaaaabab
+bbbaaaaabbbbaabababbbbba
+abbabbbaabbbabbbbaaaabbababbaaababbbaaaa
+aaabbaaababbbabaaaababaa
+ababaabbabaaaaaaaaaaababbbaaabbbbbbababababbabbaaaaabaabaaabbbab
+baababaabbbaabaabababbaabaabbbbabbbbbabb
+abbbabbbaabababaabbbaabb
+baaaabbaaababaabaabaaabbabbabaabbaaabbbababbbaaa
+baababaababbbbaabbaaaaaabbbbaaababaabbaaabaaaaabaaaaabbb
+abbabbbbbaaabbbbabbbaaaa
+abbbbabababaaaaaabbaaaaababbbbbabbbbabab
+bbbaaabbabaaaaaaaaaaaabbababaaaabbaaaaabaabbaaaa
+bbbbaabbbababbaaabababbabaaaabaabaabaaaa
+baaababbabbaaaababbabbaa
+abaaaaabbbabaaabaabaaaabaaabababbbaaababaaababaabbaaabab
+bbbaaaabbababbbbababbbba
+baaababbbababaababbbbabb
+aaabbbbbabbabaababbaaaabbaabbaba
+baabaabbaaababababbbbbaababababbaabaabbaaabaaababbabbbaabaabbabbaabbabba
+baaaabbbbabaaaaabbabaaabaabaaaabbbaaaababbaaaabaabaabaaaabaabaaaabbbabbaaabbaaab
+bababbbbbbbbaabbabbababbbabaaaaabbbabaab
+baaabbababaabbababaabaab
+abbaaabbbbbbaabaabbbbababababbbbababaaba
+bbbbaabaabbaabbaabaabbbb
+baababbbbbbbbababaaaabbbaaaaabbb
+aaaabbabbabbaababbabaaababbaabab
+aababbbabaabaabbbbbaabaabbabbbaa
+abaabbaabbaabbbbaabbaabb
+bbbaaaabaaabbbbabaaabaaabbababbbaabbbaab
+abaabbaaaaabaabbbbbbbababbbbbababbbaabbbbbaabbba
+baababbbbbbababbaaaaabaababbbbba
+abbabaaaaababaabababbaaabbaaabbabaaabbaa
+abaaabbaabababaaaabaaabbbababbbbbaabbbbbaabbabbaababbbab
+bbaabbbbbbabbbbaabbaabaababbbaababbababbbbabbabaabbaabbbaabbaaaa
+baabababababaaaaaabbabba
+babababbbbaaabaaabaabbbb
+abbabaaaaaaaabaaabaaabbababbbbaabababaabaaaaaaaaaabbbbbaaaaabababbababba
+bbabbabbabaaabbaaabbabab
+aabbbbbbbbaababbbaaabaaaaabaaaba
+bbaababbabbaaaabababaaba
+bbabaabbbaabbbbbabaaabaabbbbbbaa
+bbbabaaabbbaaaababababbaabaaababbbbaaabbbbbabbaabbabaababaaababa
+abababaaaababbbababbabab
+bbbbbabaabbababbbbabbabbaabbaaaa
+babbaabababaaaabbbaabbaa
+bbbaabbbbababababbabbaab
+bbbaabaaabaaaaaaababbbbbbbaaaabababbabababbaaabbababaabbabbaabaabbbabbaa
+bbbbabbabababbaaaaaabaab
+babbbaabbababbabaaababbbaaababbaaabbaabb
+abaabbababaababbabbbaaabbbbbabbb
+bbbabaaabaaaabbababbbabbabbbabbbabbbbbbabbabbaaa
+bbabaabbaaabaabaabbabbabaabaaabbaabbbbaa
+bbababaabaaaaaabbabbbbaabbaabaabaabbbababbaabbba
+abbaaabbbaaabbbbbabbbabbaaabbbaa
+bbbabaaaabaaabbaabbabbaa
+abbbbbbaabbabaaaababbbab
+abbbabbbaaaabaaaabbbbbaababaaaababbabbbaaabbbbba
+abbabaabbaaabaaaaabaabbbaaabaabaabbbaaaa
+bbbaaaaaabbaaaaabaabbbaaabaaaababaaaaabb
+baabbbbabababbbabababaabbaaabbabaabbbbaa
+aabaabbbabbabbabbabbabba
+babbbabbbbbaabbbaababbbabbabaaababbaabab
+bbbaabaaaaaabaaaabbbabaababaaaaababaabaaaabbaaabbabbabbb
+aabaabbbbaabababaaaaabbb
+baababaabaaabbabbaaabbaa
+abababbabaabbbabbbaaaabaabbaabbabbbbabbb
+abbbabbbabbababbbababaaa
+bbabbbbaabababbaabbabaabababbaaaaabbabaabbbbabab
+aaabbabababbbabbaabbbbab
+bbaabababbaaabbbaabbbbab
+baaabbaababbbbbaaabaaabaabaabbbababbaaab
+bababbbbbbbbaabbbbbbabaa
+bbaaaabaaaaabaaaabbababaaabbbaab
+aaabbaabaaaabbabbbaaabababbbbababbbaababbbaaaabbabaabbab
+ababbaabaabbbbbbbabaaaabaaaaaaab
+baaabbbaaaabbabaababbbab
+bbbbaababaabaaababbbabbbbaaabbbbaaaaaabbbabaabaaaabbabbb
+bababbaaaaaabaaabbbaababaaaaabbaabbaaaaaaabaaaaaabaabbbbbabbbbababbbaabb
+aaabbababaaabbbbabbaaaaaaaaabbbaaaabbbaababaabbb
+aabaaaabaaaabbbabababababbbbaabaaabaaaaa
+aaaabbaaabbabbbaabbabaaababababbabbabaaaabbaabbb
+aaaabbbbbbababbaabbbaabbbabbbbaaabbaaabbbababbaabbbababbabbbababbaababbbaababbaaaaababbb
+babababbbbabaabbbbaaaabb
+abaabbabaaabaababbababaabbabaaababbbbaaa
+aaaaabaabaaaabaaaaabbaaa
+baaabbbaabbaaabbaababaabbbaaaaaaabbbaabb
+babaaaabbaabbbabbbbabaab
+baaababbbbbbbaaaaaaaabaaababbbabaaaaabab
+bbbaabaabaabbbabbbaabbba
+aaaaabbbabaabbbaabaaabbaabbbbbabaaaabaabaabbabbbbbbabbbbbbabbbbaaaaabbaa
+abaaaaabbabbaababbaababbaaaaabaaababbaaaaaaabbbbbaabbaaa
+babaaaabbbaababbbaabbaaa
+babbbbaaabaabbaababaaaabbbababaabbbbbbaababaabaa
+baaaaaababababaabbbabbba
+bbaaabaabbaaabaaaabaabbaabbaabbaaabbaaaa
+aaabbbbbaaabaababbbbbaababbbaaababbabbbabbbbbbbbaaaababbabbbaaba
+bbaabaabbbbbbaaabababbab
+baaabbbbbbbbbabbbaaaaabb
+aabbbabbbaaaabbbaabaaabbaaabaabaabaabbbbbaabaaba
+abbaaaaabbbbbaaaaaaabbbababbabba
+bababbbaababbabaababaaab
+bababbaaabbbbbabbbabbaab
+bbabaabbaaabaababbbbabbaaaaabbbaaaabbbbabbabbaab
+bbabaabbbaaaabbaabbbbbaababbbbaaaabbbbba
+babaaaabbababababbaaaabababbaaab
+bbbbaabaaabababaaabbbbbababbbababaaaaaabbbaabbabaaabbbaa
+baaabbbbabbababaabababbaabbaabababaabaaa
+bbabaaabaababababaaaababbbbbbbababbaababaabbbaab
+bbbbbabbaababaaabbbbbababbbababa
+bbbabaaaaabbbbbbbaabbaab
+bbbbabbaabbbbbababaaabbaaaabbbbbbbbbbabababbaabb
+abbabbabbbbbabbabaaaaaaa
+bbaabaabbabbbbaabbbabbaababbbababbababbbbbbbabbb
+abababbbaaaababbbabbaabb
+bbabaabbaaaaabaaabbabaabaabaaaba
+bbabbbbaaaabababbbabbbbb
+bbaaaaabaaabbabaabbaabaaaabbbabaaabaaaaa
+baaaaaabaabaaabbbaabababaaabaaababaaabbbbabaabaabaabbaba
+bbbababbbaababbabaaaabaabbbaabaaabababbbababbbbb
+bbaababbbabbbabbaababbbababababbbbbaaaba
+baaabababbabbabbabbbbabbbabaaabaaabbaabababbbbbbbaabbbaa
+ababaaaabbbbbabaabaabbabababbabbaabbabba
+bbabbabbbabababaaabbaaba
+baaabbbaabababbbbaabbabbaabbaabbbababbbaabbaaabbbabaaabbaaabbbab
+aabababaabaaabbaaaaababb
+babaabbaaaabbbbbaaababaa
+aaabaaababbbbabbabbabaababababab
+abaaaaaabbabbabbababbaabbabaabaa
+aaaaabaaabababaabbababba
+babbaabbaaaabababbabbbbbaaaababa
+bbaabbbbbababaababaabbbb
+bbaaaaaabbbbaabbbbbaaabbaaabbaabaababbbb
+bbabbbbaaababbaaabbabbaaabbbaabaaababbab
+bababababaaaabaaabababbb
+baaabbbaaabaaaaaaabbbbba
+baabbbbabbbaabaaaaaabbababbaaaaabbaaabbb
+babaabbabbbbbabaabaaaaaabbbabbaaabaabbba
+babababbbabbbbaaabbaaaababaaaaabababbaaaaaabbbabababbbabababbbbbbbbbabbb
+aabaabbbaaabbbbaabbabbabbabbababbaaaaabb
+baaabaaabaaabbabaaaabbabbbaabbaaabaabaaa
+aaabaababbbbbbabaabbbbbbaaaabaab
+aabbabbbbbbbbbbbababbbabaaabbbaa
+bbbaabbbababbababbbbaaabbababbbabbababba
+bbabbbbabaaabaaababababbaabbaaaa
+abbabbabbaaababbbbbaaaba
+baaabbbabbbbabbabbbbabbb
+abbbabaabbaabaaabbbaaaababbababbabbbaaaaaabbaabb
+bbbbbaaabababbbabbbaaaba
+baaaababbbaababbaababbaa
+baabbbbabbaabaaaaabbaaba
+abbbabaabbbaababbbabaaabaaaabbaabbabaaba
+bbababaabbbabaaabababbbbabaaabbb
+ababbaaaabbbbbabbbabaaba
+bbbbaabbbbbaaaabbbaabbbaaaabbabb
+bbbbbbababbabbbbabbaaaababbbbbbbbbabbbbb
+abbaababbbaabbaaaaabbbababaababaabaaabaaaaaababb
+baaabaaabbbbabbababababaaabaaabbabbaaabbbaabbabb
+baabbbaaaaaaabbaabaaaaababbabbabbbaaabab
+ababababbabbaabbbabbabbbbabaaaaaaaaabbbb
+baababbabbbaabbbabaaabbaabbbabba
+bbaabbbbbbaababbbabababbbbbaaabbabbaaaaabbbbbbbbbbbbabaaabbbaaaa
+baaaaabaaabaaaabaaabbbbaababbaabbbbbbabaaababbaa
+abaabbaaabaababbbbaabbaa
+baaabaaabbaaaaaababaabab
+bbbbaaabbabababbbbaaabba
+aaaaaabbababbabbabbabababbabaabbaabbabbbbbbaaababbabbaba
+bbbbbabababaaaabaabbaaaa
+baaaabaaaaabbbbbbababbbbbbbaabbbbaaabaabababbbaa
+bbaaaabaabbbbbaabbaaabaaaababaaabaaaabaababbaaab
+bbaabbbbbbaaaabaaaabbbbbbbaaabaaababbaaaabbaaaabaabaaabaabbbabbaababbbab
+bbbbaababaaabaaaaabbbbba
+aaabbbbaabababaabbaababaaaabababaaaaaaaa
+bbaabaabaaaabbbabababbaaabbbbbaabbabaabaaaabbbab
+aaabaaabbbaabaaabaaabbababaabbabbbabbbaa
+abbabaababbabbbabbbaaabbbbbababa
+aaabbbbbaabaabbababbbbba
+baaaabaabbaababbababbbba
+bbbbbbabbabbbaaaababababaababbbaaababbbabaabbbbaabaabbaaabbbbaaa
+abbabaabbaaabaaabaabbaaabaabbaaababbbbbbbbbbaabaabaabbab
+abbbbbbbbbbababaaaabaaaaabaababaababbbbababbaaaa
+ababbabababbbaababbabbbaabbabbbbbbabbaaa
+baaaabaababaabbabbaaaaaabbbaaaaaabaaabababaaaabbbabbaaaa
+abbbbbaababbbaababbaaabbbbaaabbbbbababab
+aabaabbaabbbbbababaabaaaabbaaabaabbaaababbbbabaaabbababbabbbbabaabbbaaaaaaabaabb
+babbaababababababbaabbba
+abbabaabaababbbababaabaa
+bbaabaaabaabababbaabababbaaababbbbbaaaabbabbbbbbababbbbaababbbbbbabbbaba
+aaabaaabbbaaabbbbbaaabaabaaaababbbabbbabababababbbbabbaa
+bbbbbbaaabbbabaababaabaaababbbabaaabbbbababaaaabbbbbbbbabaaababbbaaabaabbbbbabbaaaabaaba
+aaabbbbabbbaabaaabbaabaabaaababaaabbbaab
+abbaaabbbbbbaabbbaababaababbbbba
+bbaaaaabbbbabaaabaaabaab
+bbbaaaaababababbbaaabbbbbaababbabaabaaaaababbbbabbababba
+ababbaaabbbbbbbaabaaaaaababaabaaabaaabaa
+baababbbbaaababbaabbbbba
+babbabbbabbabbaabababbbbaaaabbbbbbbbaaabbabbaabaaababbab
+bbabbabbabbaaaabbaabbbaaaaabaaababbbbbabbabbabba
+bbbbaabababababbbabaabab
+abbbbabbababbaabaabbabab
+aaabaabbbbbabaaaaababbab
+baaaaabaabaaabbabbaabbbbbaaabbaa
+bbbbaabaababbababbbabbab
+aababaaabbbbbbbabbbababbbabbaabbabaaabbb
+aabbbaaaaaaaabaabaaaaaabaabbbbbbaabababb
+aaaaaabbbaabaabbaabbabba
+aaaaabbaaaabaabbabaababa
+aaabababbbbaaabbabbaaabbbbbaaaaababaaaaaababbababbbabaab
+abaababbabaabbabbbbaababbbaabbba
+aababaaabbbbbabaabbabbbbabbabbbbaaabbbbbabbababbbbaaabababaaaaba
+aaabaaababbababbaaaabbbabbbbabaaaabbbaba
+bbababbbaaabbaababaabbbbaaaabbbabaaaabbababbabbbabbaaaaaabbaaabababaabba
+aaaabbaabaaaaaabbababbbbaababbaa
+abaababbaaabbbbabbaabaabbbbbaabaababbbabbabbaaab
+aababbbbaabbaaaabbaabbabababbabaaabaaaaabaaaabbbabababab
+babbbabbbbbaaabbaabbabbb
+bbaaaaaaaabbbabbaabaabbabbbbaaaabbababba
+bababbbbbbbaabbbbbbabbab
+bbbaaabbabbbbbaaababbbbb
+abbbbbbbbbbbbaabaabbabbabbbbbabbaabbabbaabaabaababbbabbbbbbbbbaabbbabaaaabbbaaba
+aabbbbbbaaaaaabbbbbbaaababbbbbabbbaabaaabbbbbbbb
+bbaabababaababbbaaabbbab
+bbbbbabbbbbbaabababbabbb
+bbabbabbabababbaaaababbbbaabababbaabbabb
+aabbbbbbbaaabbabaaabbbbbbaabbaaaaaaabbbb
+bababbbaababbaabbaaababbabbabbbbbababbbaaaabbbbbabbabbaa
+aabbbaaaaaaabaaaaababaaababbbbabaabaabab
+abbaabaaaaabaaabbbaaabbbaaabbbbbbbbbbbaaaabbaabaababbbbb
+bbbabbbababababaabbabbbaaaaaabaaaaaaabaabbbbaabaaabbabaabaababbbaaaaabaaabbbbbbbbaaabbaabaaaabaa
+baabaaabbaabbbaaaaabbbaa
+babaaaaaabbabbababbbabba
+bbbbaabbbbabbbbaaaabbbbb
+aabaaabbbabbbabbbbabaabbaabbbabbbbaaabaabababaaabbabbaaaabbaabbaaabababb
+bababababbbbaaaabaabbbbaaababbaaaaabbaab
+bababaabbaaaababaaaaaaba
+abbababbbabbaabababbbbaaaabababaaaabababbababaaa
+abbaabaaabbabaabbbaaabbbbaaabbbb
+abaaababbbaababbabbbabbbaaababaa
+bababbbbabbbbababbbabbab
+baaabbbababbbabbaabbbbba
+aaaabbbabbaaabaaaabbbaaabbababba
+bbbaaaabbbabbbbaabbbabba
+abaaaaabbbbaaaaabbabaaabaabbabbababbbbbb
+aaaaabbaaaabababbbbaaaba
+ababaaaaabaabbabbbbaababbbbbbbaababbaaaa
+babbbabbabaaaaaabababababaabaababbbabbaa
+aaaaaabbaaabaababbaaabba
+baabbbaabbababaabbbbaaaabbaabaabbabaabbbaaaababa
+abbabaaabaaaabbbaaaaabbb
+aababbbaabbbbbabbbababaabbbaabababbbabaaabbbbaab
+abbabaaababbabaaabbabbabbaabbbab
+bbabbbbaabbbbbabbbaabaabaaabaababbbabaababaaabbbabbaabba
+abaabbbabaabbabababaaabbbaabbabaaaababaababbbaabaababbab
+abababbabbbababbabbbbabbbabaabab
+aaaaabbabaaabaaaabaaabaa
+aaabbbbabbabbabbababaaaaaaaaabaabaabbbbb
+ababbababbbbabbabbbaaaaabbabbaba
+abbbbbbababbbbaaabbabaabaabababb
+bbaaabaaaaaabaababaabbabababbaaabbaababbaaabaababbaababbaabababbbaaababaaabbaaabbbbbbaaa
+aaaabaaabaababbbabbbbbbaabaabaaa
+bbaabaabaababaaaabbbabaabbaabbab
+abbbabaaaaaaaabbaababbbaabaaaaababaaaaaabbaabbaa
+abbabbababbbabbbabbbabbbaaaabaaabbaabbaaabbbabbabbbbbbbb
+bababaabaababbbaabbababaababaaab
+bbaaabaaababbaaabbaabbba
+aabaabbaabaaaaaabbababbb
+ababbbbbbbbbbabbbabbaabbbbbaabababababbabbaabbabaaaabbbbabbbbaab
+abaabbaaabbababaabbbaabb
+ababaaaaabbabbbababaaaba
+baabaabbabaabbaabaababaaabbbbbbbaababaaabaaabbaaabaabbbb
+baaabbabaaabbbbbaababaabbabaaabaaaababaa
+bbaaabbbbbbbaaabaaaaaaba
+aabaaaababbaaaabbbbbbabbaabbaaba
+abaabbababbaaaabbababbbaaaabbabb
+bbaaababbaabbbababaaaaabbababaabaaaabbaaababbaaaaaaaababaaabbaab
+aababbbabababbbaabbbabba

From 6b74fe74aa7a27596314c2e9c0a6bb66343a72b4 Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Wed, 23 Dec 2020 16:35:27 -0800
Subject: [PATCH 11/12] Completed day 23

---
 2020/days/day23.cpp     | 105 ++++++++++++++++++++++++++++++++++++++++
 2020/inputs/day23.input |   1 +
 2 files changed, 106 insertions(+)
 create mode 100644 2020/days/day23.cpp
 create mode 100644 2020/inputs/day23.input

diff --git a/2020/days/day23.cpp b/2020/days/day23.cpp
new file mode 100644
index 0000000..f3cc3b4
--- /dev/null
+++ b/2020/days/day23.cpp
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <vector>
+#include <array>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+constexpr auto CUP_COUNT = 9;
+
+auto day23() -> void {
+	auto start = usize(0);
+	auto nums = std::array<usize, CUP_COUNT>();
+	auto big_nums = std::vector<usize>(1000000);
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day23.input");
+		getline(file, line);
+		for (auto i = usize(0); i < CUP_COUNT; ++i) {
+			nums[line[i] - '1'] = line[(i + 1) % CUP_COUNT] - '1';
+		}
+		start = line[0] - '1';
+		for (auto i = usize(0); i < CUP_COUNT; ++i) {
+			if (nums[i] != start) {
+				big_nums[i] = nums[i];
+			} else {
+				big_nums[i] = CUP_COUNT;
+			}
+		}
+		for (auto i = CUP_COUNT; i < big_nums.size() - 1; ++i) {
+			big_nums[i] = i + 1;
+		}
+		big_nums[big_nums.size() - 1] = start;
+	}
+
+	auto begin = usize(0);
+	auto end   = usize(0);
+
+	// Part 1
+	auto current = start;
+	for (auto i = usize(0); i < 100; ++i) {
+		begin = nums[current];
+		end   = nums[nums[begin]];
+		nums[current] = nums[end];
+		auto destination = current;
+		while (
+			   begin       == (destination = (destination + CUP_COUNT - 1) % CUP_COUNT)
+			|| nums[begin] ==  destination
+			|| end         ==  destination
+		);
+		nums[end] = nums[destination];
+		nums[destination] = begin;
+		current = nums[current];
+	}
+	auto out = std::array<c8, CUP_COUNT + 1>{ 0 };
+	for (auto i = nums[0], j = usize(0); i != 0; i = nums[i], ++j) {
+		out[j] = (i + '1');
+	}
+	print(&out[0]);
+
+	// Part 2
+	current = start;
+	for (auto i = usize(0); i < 10000000; ++i) {
+		begin = big_nums[current];
+		end   = big_nums[big_nums[begin]];
+		big_nums[current] = big_nums[end];
+		auto destination = current;
+		while (
+			   begin           == (destination = (destination + big_nums.size() - 1) % big_nums.size())
+			|| big_nums[begin] ==  destination
+			|| end             ==  destination
+		);
+		big_nums[end] = big_nums[destination];
+		big_nums[destination] = begin;
+		current = big_nums[current];
+	}
+	print(((big_nums[0] + 1) * (big_nums[big_nums[0]] + 1)));
+}
diff --git a/2020/inputs/day23.input b/2020/inputs/day23.input
new file mode 100644
index 0000000..f5a2d22
--- /dev/null
+++ b/2020/inputs/day23.input
@@ -0,0 +1 @@
+247819356

From 3b0619a2ca0cb47047e8797e1c1dd5d55cdaab86 Mon Sep 17 00:00:00 2001
From: Gnarwhal <git.aspect893@passmail.net>
Date: Sun, 6 Oct 2024 21:15:16 +0000
Subject: [PATCH 12/12] Piss poor attempt at AoC 2021 and I'm 3 years late
 publishing it :/

---
 2021/Makefile              |   17 +
 2021/days/day1.cpp         |   54 +
 2021/inputs/day1.input     | 2000 ++++++++++++++++++++++++++++++++++++
 2021/misc/day.cpp.template |   23 +
 2021/misc/main.cpp         |   36 +
 2021/misc/main_test.cpp    |   66 ++
 2021/misc/print.hpp        |   31 +
 2021/misc/types.cpp        |   47 +
 2021/misc/types.hpp        |   70 ++
 9 files changed, 2344 insertions(+)
 create mode 100644 2021/Makefile
 create mode 100644 2021/days/day1.cpp
 create mode 100644 2021/inputs/day1.input
 create mode 100644 2021/misc/day.cpp.template
 create mode 100644 2021/misc/main.cpp
 create mode 100644 2021/misc/main_test.cpp
 create mode 100644 2021/misc/print.hpp
 create mode 100644 2021/misc/types.cpp
 create mode 100644 2021/misc/types.hpp

diff --git a/2021/Makefile b/2021/Makefile
new file mode 100644
index 0000000..2978a55
--- /dev/null
+++ b/2021/Makefile
@@ -0,0 +1,17 @@
+day%.out: out/types.o misc/main.cpp days/day%.cpp
+	g++ -O3 -std=c++2a $(flags) -Dcurrent_day=$(@:.out=) days/$(@:out=cpp) misc/main.cpp out/types.o -o $@
+
+day%_test.out: out/types.o misc/main_test.cpp days/day%.cpp
+	g++ -O3 -std=c++2a $(flags) -DTEST_BUILD -Dcurrent_day=$(@:_test.out=) days/$(@:_test.out=.cpp) misc/main_test.cpp out/types.o -o $@
+
+days/day%.cpp:
+	cp 'misc/day.cpp.template' $@
+	sed -i -e "s/current_day/$(shell basename $@ | cut -f 1 -d '.')/g" $@
+
+out/types.o: misc/types.hpp misc/types.cpp
+	mkdir -p out/
+	g++ -std=c++2a $(flags) -c misc/types.cpp -o $@
+
+.PHONY: clean
+clean:
+	rm -f out/* day*.out day*.output
diff --git a/2021/days/day1.cpp b/2021/days/day1.cpp
new file mode 100644
index 0000000..4f8c65c
--- /dev/null
+++ b/2021/days/day1.cpp
@@ -0,0 +1,54 @@
+/*****************************
+ *
+ * Copyright (c) 2021 Gnarwhal
+ *
+ *****************************/
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+auto current_day() -> void {
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day1.input");
+		getline(file, line);
+		auto value     = stoi(line);
+		auto increases = 0;
+		while (getline(file, line)) {
+			auto new_value = stoi(line);
+			increases += new_value > value;
+			value = new_value;
+		}
+
+		std::cout << increases << std::endl;
+	}
+
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/day1.input");
+		getline(file, line);
+		auto index     = 2;
+		auto values    = std::vector<i32>{ 0, 0 };
+		while (getline(file, line)) {
+			auto new_value = stoi(line);
+			values.push_back(0);
+			values[index - 2] += new_value;
+			values[index - 1] += new_value;
+			values[index    ] += new_value;
+			++index;
+		}
+
+		auto increases = 0;
+		for (auto i = 3; i < values.size(); ++i) {
+			increases += values[i - 1] < values[i];
+		}
+
+		std::cout << increases << std::endl;
+	}
+}
+
diff --git a/2021/inputs/day1.input b/2021/inputs/day1.input
new file mode 100644
index 0000000..bc99d0b
--- /dev/null
+++ b/2021/inputs/day1.input
@@ -0,0 +1,2000 @@
+199
+227
+229
+230
+233
+228
+231
+226
+237
+259
+262
+265
+266
+265
+269
+276
+278
+279
+281
+287
+305
+316
+314
+320
+313
+314
+315
+329
+346
+357
+370
+369
+360
+384
+383
+401
+402
+403
+404
+403
+406
+408
+406
+401
+393
+395
+416
+418
+408
+411
+412
+416
+417
+404
+421
+436
+437
+436
+420
+388
+405
+403
+371
+376
+378
+374
+378
+377
+403
+411
+444
+424
+417
+416
+419
+436
+415
+413
+429
+446
+462
+463
+464
+467
+466
+475
+483
+478
+487
+488
+469
+470
+472
+473
+460
+463
+465
+477
+487
+508
+506
+509
+512
+513
+519
+525
+531
+498
+506
+504
+506
+507
+509
+510
+512
+537
+553
+536
+533
+524
+525
+526
+527
+530
+531
+533
+537
+538
+537
+539
+544
+552
+550
+576
+560
+556
+561
+552
+560
+572
+573
+572
+571
+573
+578
+581
+582
+578
+541
+546
+537
+545
+556
+565
+566
+571
+561
+573
+579
+578
+581
+600
+603
+604
+597
+598
+599
+598
+599
+580
+585
+586
+596
+597
+602
+593
+598
+599
+604
+608
+609
+616
+615
+613
+622
+625
+620
+632
+636
+628
+633
+640
+621
+620
+638
+646
+647
+648
+647
+654
+655
+663
+652
+664
+668
+669
+668
+663
+667
+659
+658
+666
+670
+685
+703
+706
+705
+706
+727
+730
+729
+735
+743
+749
+750
+751
+756
+774
+776
+767
+778
+777
+790
+791
+794
+798
+801
+804
+812
+818
+819
+818
+821
+825
+818
+829
+832
+835
+849
+848
+863
+859
+863
+871
+870
+869
+873
+875
+878
+874
+896
+903
+890
+891
+905
+912
+913
+911
+917
+941
+943
+944
+940
+943
+945
+947
+948
+953
+930
+932
+933
+948
+936
+937
+941
+947
+952
+957
+951
+953
+954
+958
+979
+982
+971
+974
+979
+984
+988
+989
+986
+987
+992
+998
+1013
+1024
+1022
+1023
+1014
+1019
+1042
+1048
+1047
+1060
+1056
+1067
+1054
+1053
+1061
+1063
+1068
+1074
+1104
+1105
+1107
+1119
+1126
+1127
+1129
+1143
+1145
+1146
+1151
+1159
+1183
+1185
+1192
+1183
+1185
+1182
+1180
+1198
+1215
+1221
+1224
+1227
+1230
+1262
+1289
+1291
+1294
+1297
+1300
+1303
+1321
+1323
+1329
+1331
+1341
+1362
+1369
+1370
+1388
+1389
+1393
+1407
+1386
+1380
+1381
+1378
+1398
+1402
+1399
+1422
+1433
+1449
+1451
+1449
+1462
+1454
+1455
+1452
+1471
+1472
+1487
+1477
+1459
+1463
+1461
+1463
+1473
+1489
+1482
+1516
+1527
+1521
+1522
+1527
+1529
+1531
+1538
+1550
+1553
+1548
+1549
+1545
+1548
+1543
+1546
+1549
+1572
+1576
+1581
+1575
+1584
+1602
+1604
+1605
+1606
+1611
+1610
+1623
+1618
+1614
+1622
+1613
+1608
+1611
+1638
+1632
+1643
+1649
+1652
+1655
+1652
+1653
+1654
+1658
+1659
+1661
+1667
+1695
+1710
+1719
+1726
+1727
+1725
+1726
+1736
+1741
+1763
+1752
+1769
+1770
+1767
+1768
+1769
+1771
+1799
+1798
+1810
+1813
+1816
+1826
+1837
+1842
+1841
+1848
+1853
+1823
+1836
+1835
+1837
+1836
+1839
+1838
+1840
+1841
+1839
+1843
+1844
+1862
+1873
+1877
+1880
+1882
+1881
+1895
+1891
+1896
+1899
+1893
+1894
+1892
+1894
+1895
+1921
+1920
+1922
+1928
+1925
+1933
+1943
+1942
+1936
+1941
+1919
+1912
+1914
+1922
+1918
+1934
+1932
+1946
+1949
+1955
+1964
+1974
+1977
+1978
+1983
+1984
+1986
+1990
+2005
+2022
+2026
+2032
+2031
+2029
+2031
+2035
+2041
+2042
+2043
+2053
+2054
+2058
+2062
+2063
+2055
+2049
+2021
+2022
+2054
+2052
+2084
+2076
+2079
+2090
+2088
+2093
+2095
+2093
+2091
+2089
+2095
+2096
+2102
+2127
+2129
+2132
+2117
+2125
+2131
+2132
+2126
+2134
+2140
+2137
+2138
+2136
+2137
+2141
+2153
+2152
+2170
+2177
+2147
+2159
+2161
+2160
+2173
+2176
+2194
+2205
+2206
+2213
+2231
+2232
+2242
+2243
+2217
+2224
+2225
+2230
+2226
+2214
+2212
+2227
+2230
+2237
+2238
+2241
+2264
+2283
+2288
+2308
+2309
+2311
+2312
+2314
+2316
+2317
+2318
+2321
+2326
+2324
+2325
+2321
+2324
+2322
+2325
+2327
+2335
+2369
+2370
+2374
+2375
+2344
+2347
+2348
+2341
+2346
+2355
+2356
+2371
+2368
+2370
+2375
+2378
+2379
+2370
+2363
+2365
+2366
+2363
+2364
+2372
+2374
+2392
+2399
+2397
+2384
+2400
+2401
+2402
+2401
+2400
+2402
+2412
+2422
+2423
+2426
+2424
+2425
+2421
+2422
+2440
+2441
+2451
+2442
+2443
+2444
+2446
+2451
+2452
+2450
+2458
+2457
+2490
+2496
+2506
+2507
+2508
+2511
+2531
+2536
+2537
+2539
+2529
+2530
+2561
+2562
+2592
+2595
+2584
+2601
+2603
+2589
+2586
+2588
+2586
+2596
+2613
+2616
+2618
+2621
+2629
+2637
+2638
+2619
+2621
+2619
+2631
+2621
+2619
+2624
+2628
+2634
+2636
+2637
+2626
+2632
+2623
+2630
+2629
+2630
+2633
+2620
+2629
+2635
+2614
+2617
+2612
+2613
+2609
+2601
+2604
+2611
+2602
+2607
+2611
+2639
+2646
+2647
+2618
+2613
+2614
+2635
+2642
+2649
+2653
+2652
+2628
+2629
+2631
+2636
+2639
+2649
+2665
+2667
+2666
+2665
+2668
+2672
+2673
+2675
+2693
+2694
+2696
+2701
+2702
+2703
+2700
+2716
+2718
+2719
+2718
+2719
+2722
+2723
+2715
+2726
+2737
+2757
+2758
+2759
+2762
+2760
+2765
+2759
+2763
+2764
+2774
+2785
+2786
+2802
+2803
+2802
+2824
+2833
+2834
+2830
+2832
+2842
+2828
+2829
+2836
+2838
+2813
+2811
+2798
+2799
+2796
+2805
+2808
+2807
+2811
+2812
+2811
+2812
+2793
+2787
+2802
+2805
+2804
+2822
+2825
+2837
+2835
+2842
+2838
+2849
+2840
+2841
+2853
+2854
+2863
+2877
+2886
+2864
+2866
+2846
+2860
+2840
+2842
+2844
+2866
+2867
+2870
+2856
+2860
+2861
+2860
+2872
+2877
+2881
+2883
+2881
+2883
+2880
+2881
+2882
+2880
+2902
+2903
+2904
+2937
+2939
+2938
+2945
+2954
+2950
+2966
+2967
+2976
+2980
+2982
+2976
+2986
+2997
+2996
+2994
+3004
+3007
+3008
+3016
+3014
+3054
+3078
+3095
+3114
+3115
+3120
+3107
+3109
+3124
+3140
+3144
+3150
+3163
+3165
+3164
+3158
+3172
+3175
+3174
+3184
+3188
+3198
+3193
+3224
+3226
+3227
+3252
+3273
+3280
+3289
+3291
+3290
+3291
+3279
+3281
+3282
+3281
+3298
+3302
+3289
+3304
+3295
+3312
+3314
+3327
+3328
+3337
+3348
+3349
+3340
+3348
+3351
+3350
+3351
+3350
+3345
+3339
+3343
+3344
+3329
+3354
+3356
+3358
+3363
+3365
+3373
+3376
+3383
+3384
+3388
+3389
+3390
+3397
+3398
+3401
+3409
+3411
+3412
+3411
+3418
+3428
+3430
+3432
+3418
+3410
+3418
+3424
+3425
+3426
+3430
+3439
+3441
+3422
+3423
+3425
+3426
+3428
+3429
+3436
+3448
+3447
+3443
+3445
+3468
+3482
+3483
+3499
+3506
+3513
+3518
+3523
+3524
+3525
+3529
+3532
+3529
+3565
+3577
+3576
+3577
+3576
+3539
+3557
+3554
+3563
+3562
+3564
+3565
+3586
+3583
+3590
+3589
+3580
+3581
+3574
+3599
+3597
+3609
+3610
+3611
+3614
+3613
+3611
+3612
+3611
+3598
+3596
+3597
+3585
+3568
+3569
+3550
+3561
+3563
+3551
+3552
+3555
+3553
+3554
+3553
+3552
+3555
+3557
+3560
+3585
+3591
+3604
+3609
+3640
+3641
+3645
+3644
+3643
+3646
+3644
+3664
+3653
+3660
+3667
+3664
+3665
+3668
+3670
+3649
+3640
+3639
+3647
+3654
+3650
+3648
+3654
+3651
+3652
+3653
+3654
+3655
+3671
+3660
+3671
+3675
+3679
+3680
+3681
+3686
+3690
+3691
+3693
+3695
+3698
+3697
+3699
+3708
+3712
+3714
+3712
+3711
+3716
+3731
+3732
+3736
+3753
+3755
+3756
+3767
+3747
+3746
+3733
+3711
+3722
+3718
+3721
+3722
+3723
+3724
+3727
+3731
+3732
+3741
+3743
+3750
+3751
+3738
+3741
+3739
+3740
+3756
+3755
+3751
+3750
+3755
+3757
+3773
+3778
+3781
+3782
+3768
+3772
+3766
+3770
+3778
+3792
+3798
+3801
+3803
+3801
+3812
+3833
+3873
+3868
+3865
+3866
+3906
+3910
+3897
+3907
+3910
+3898
+3914
+3917
+3908
+3912
+3920
+3934
+3930
+3934
+3935
+3937
+3942
+3943
+3948
+3964
+3978
+3985
+3986
+3993
+3995
+4014
+4021
+4024
+4025
+4024
+4027
+4028
+4043
+4047
+4049
+4036
+4039
+4038
+4037
+4045
+4040
+4041
+4043
+4035
+4046
+4063
+4054
+4055
+4064
+4067
+4060
+4061
+4062
+4069
+4070
+4063
+4064
+4077
+4065
+4074
+4076
+4078
+4091
+4100
+4104
+4105
+4106
+4107
+4115
+4110
+4112
+4113
+4114
+4115
+4092
+4093
+4107
+4109
+4108
+4112
+4143
+4144
+4145
+4146
+4145
+4144
+4126
+4130
+4134
+4149
+4151
+4161
+4162
+4160
+4146
+4170
+4188
+4196
+4194
+4193
+4196
+4197
+4198
+4200
+4205
+4218
+4228
+4216
+4224
+4226
+4241
+4245
+4247
+4251
+4245
+4244
+4266
+4259
+4262
+4269
+4270
+4275
+4281
+4298
+4305
+4309
+4311
+4325
+4328
+4346
+4347
+4357
+4360
+4359
+4357
+4391
+4396
+4391
+4397
+4395
+4405
+4410
+4412
+4433
+4420
+4421
+4422
+4423
+4431
+4437
+4447
+4451
+4458
+4457
+4458
+4456
+4455
+4458
+4460
+4431
+4432
+4431
+4441
+4444
+4436
+4408
+4406
+4414
+4415
+4413
+4422
+4449
+4430
+4428
+4397
+4395
+4396
+4398
+4396
+4399
+4406
+4413
+4422
+4421
+4429
+4431
+4430
+4462
+4460
+4480
+4482
+4486
+4484
+4483
+4497
+4493
+4496
+4506
+4504
+4497
+4498
+4503
+4513
+4525
+4533
+4547
+4560
+4561
+4563
+4562
+4572
+4571
+4575
+4557
+4561
+4562
+4550
+4552
+4543
+4537
+4534
+4542
+4561
+4563
+4562
+4583
+4582
+4591
+4592
+4597
+4601
+4599
+4600
+4610
+4601
+4612
+4630
+4616
+4619
+4623
+4624
+4636
+4638
+4645
+4651
+4655
+4660
+4659
+4658
+4657
+4658
+4661
+4670
+4665
+4656
+4664
+4666
+4667
+4669
+4696
+4701
+4712
+4711
+4719
+4679
+4680
+4686
+4684
+4685
+4689
+4682
+4686
+4688
+4687
+4688
+4687
+4693
+4672
+4670
+4667
+4673
+4643
+4644
+4653
+4668
+4669
+4672
+4685
+4663
+4665
+4672
+4696
+4698
+4701
+4699
+4687
+4690
+4687
+4684
+4685
+4687
+4689
+4685
+4692
+4690
+4696
+4702
+4703
+4704
+4717
+4718
+4719
+4711
+4717
+4719
+4726
+4722
+4736
+4735
+4739
+4748
+4741
+4738
+4736
+4737
+4736
+4740
+4748
+4749
+4757
+4760
+4768
+4754
+4756
+4772
+4773
+4775
+4770
+4766
+4769
+4762
+4771
+4773
+4775
+4776
+4778
+4782
+4770
+4763
+4765
+4764
+4765
+4764
+4777
+4780
+4786
+4797
+4803
+4812
+4811
+4818
+4823
+4820
+4821
+4831
+4834
+4862
+4865
+4856
+4857
+4863
+4860
+4861
+4858
+4846
+4848
+4852
+4853
+4854
+4856
+4832
+4833
+4832
+4830
+4826
+4833
+4851
+4852
+4855
+4856
+4857
+4852
+4854
+4860
+4863
+4887
+4878
+4879
+4880
+4893
+4888
+4891
+4892
+4896
+4897
+4900
+4905
+4903
+4909
+4927
+4942
+4946
+4952
+4970
+4971
+4987
+4990
+4991
+4990
+4989
+4988
+4989
+4995
+4996
+5004
+5003
+5005
+5009
+4997
+4981
+4977
+4979
+4982
+4984
+4994
+5005
+5009
+5008
+5036
+5034
+5033
+5030
+5032
+5034
+5030
+5031
+5034
+5070
+5072
+5071
+5073
+5077
+5078
+5070
+5084
+5085
+5091
+5071
+5080
+5075
+5070
+5067
+5072
+5075
+5082
+5085
+5091
+5104
+5120
+5123
+5122
+5105
+5120
+5128
+5116
+5118
+5122
+5120
+5140
+5142
+5145
+5148
+5152
+5153
+5154
+5157
+5172
+5179
+5177
+5185
+5191
+5200
+5201
+5207
+5205
+5206
+5198
+5205
+5186
+5188
+5197
+5194
+5203
+5204
+5205
+5208
+5214
+5220
+5219
+5224
+5227
+5241
+5233
+5253
+5283
+5287
+5291
+5289
+5296
+5297
+5294
+5288
+5289
+5290
+5278
+5290
+5288
+5294
+5295
+5294
+5292
+5289
+5299
+5283
+5285
+5290
+5289
+5291
+5302
+5304
+5305
+5315
+5316
+5323
+5337
+5341
+5345
+5346
+5358
+5361
+5367
+5348
+5354
+5344
+5339
+5342
+5341
+5354
+5356
+5355
+5354
+5355
+5356
+5342
+5348
+5350
+5351
+5355
+5378
+5380
+5404
+5405
+5407
+5417
+5419
+5411
+5412
+5413
+5416
+5420
+5391
+5377
+5386
+5387
+5390
+5383
+5385
+5384
+5390
+5389
+5390
+5409
+5414
+5424
+5427
+5428
+5430
+5443
+5435
+5430
+5427
+5428
+5422
+5452
+5460
+5464
+5465
+5472
+5473
+5481
+5480
+5481
+5482
+5483
+5493
+5495
+5492
+5501
+5517
+5519
+5527
+5532
+5529
+5532
+5542
+5532
+5550
+5551
+5560
+5543
+5549
+5555
+5554
+5555
+5552
+5562
+5563
+5564
+5566
+5568
+5571
+5549
+5556
+5557
+5563
+5564
+5567
+5563
+5570
+5559
+5580
+5585
+5568
+5569
+5562
+5578
+5579
+5565
+5567
+5583
+5584
+5592
+5590
+5593
+5595
+5594
+5597
+5582
+5588
+5594
+5596
+5598
+5597
+5595
+5605
+5593
+5590
+5599
+5603
+5597
+5632
+5621
+5624
+5628
+5634
+5662
+5663
+5666
+5674
+5678
+5677
+5678
+5679
+5680
+5681
+5687
+5690
+5685
+5684
+5683
+5689
+5690
+5691
+5689
+5694
+5698
+5701
+5698
+5733
+5757
+5767
+5794
+5812
+5804
+5802
+5810
+5826
+5856
+5855
+5860
+5861
+5846
+5865
+5885
+5874
+5883
+5888
+5892
+5894
+5877
+5840
+5841
+5814
+5815
+5818
+5821
+5822
+5819
+5818
+5842
+5849
+5850
+5851
+5854
+5856
+5854
+5851
+5864
+5866
+5867
+5871
+5874
+5879
+5888
+5886
+5890
+5894
+5889
+5875
+5863
+5847
+5857
+5853
+5858
+5859
+5862
+5867
+5862
+5866
+5874
+5875
+5894
+5897
+5877
+5886
+5887
+5891
+5881
+5886
+5885
+5886
+5887
+5888
+5892
+5891
+5903
+5902
+5901
+5902
+5903
+5908
+5905
+5912
+5914
+5920
+5927
+5916
+5917
+5918
+5921
+5931
+5939
+5942
+5943
+5949
+5962
+5990
+5985
+5982
+5980
+5979
+5990
+5995
+6012
+6029
+6038
+6050
+6051
+6057
+6052
+6061
+6060
+6050
+6058
+6059
+6060
+6064
+6065
+6092
+6091
+6090
+6089
+6085
+6101
+6107
+6110
+6109
+6120
+6117
+6110
diff --git a/2021/misc/day.cpp.template b/2021/misc/day.cpp.template
new file mode 100644
index 0000000..c2f20b4
--- /dev/null
+++ b/2021/misc/day.cpp.template
@@ -0,0 +1,23 @@
+/*****************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ *****************************/
+
+#include <vector>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+#include "../misc/types.hpp"
+#include "../misc/print.hpp"
+
+auto current_day() -> void {
+	{
+		auto line = std::string();
+		auto file = std::ifstream("inputs/current_day.input");
+		while (getline(file, line)) {
+			
+		}
+	}
+}
diff --git a/2021/misc/main.cpp b/2021/misc/main.cpp
new file mode 100644
index 0000000..c4752db
--- /dev/null
+++ b/2021/misc/main.cpp
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include "types.hpp"
+
+extern auto current_day() -> void;
+
+auto main(i32 argc, char * argv[]) -> i32 {
+	current_day();
+
+	return 0;
+}
+
diff --git a/2021/misc/main_test.cpp b/2021/misc/main_test.cpp
new file mode 100644
index 0000000..0d8954d
--- /dev/null
+++ b/2021/misc/main_test.cpp
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include <iostream>
+#include <string>
+#include <chrono>
+
+#include "types.hpp"
+
+extern auto current_day() -> void;
+
+auto main(i32 argc, char * argv[]) -> i32 {
+	auto TEST_CYCLES = 1;
+	if (argc >= 2) {
+		TEST_CYCLES = std::stoi(argv[1]);
+	}
+
+	std::cout << "Starting test with " << TEST_CYCLES << " iterations..." << std::endl;
+	auto begin1 = std::chrono::high_resolution_clock::now();
+
+	for (auto i = usize(0); i < TEST_CYCLES; ++i) {
+		current_day();
+	}
+
+	auto end1 = std::chrono::high_resolution_clock::now();
+
+	if (argc >= 3) {
+		if (argv[2] == std::string("millis")) {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(end1 - begin1).count() << " milliseconds"<< std::endl;
+		} else if (argv[2] == std::string("nanos")) {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::nanoseconds>(end1 - begin1).count() << " nanoseconds"<< std::endl;
+		} else if (argv[2] == std::string("micros")) {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::microseconds>(end1 - begin1).count() << " microsenconds"<< std::endl;
+		} else {
+			std::cout << "Unkown time scale '" << argv[2] << "'" << std::endl;
+		}
+	} else {
+			std::cout << "Tests completed in " << std::chrono::duration_cast<std::chrono::microseconds>(end1 - begin1).count() << " microseconds"<< std::endl;
+	}
+
+	return 0;
+}
+
diff --git a/2021/misc/print.hpp b/2021/misc/print.hpp
new file mode 100644
index 0000000..5960cd8
--- /dev/null
+++ b/2021/misc/print.hpp
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#ifndef TEST_BUILD
+#define print(x) std::cout << (x) << std::endl
+#else
+#define print(x)
+#endif
diff --git a/2021/misc/types.cpp b/2021/misc/types.cpp
new file mode 100644
index 0000000..cc4d3da
--- /dev/null
+++ b/2021/misc/types.cpp
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#include "types.hpp"
+
+constexpr auto operator "" _u8   (unsigned long long int num) noexcept -> u8    { return    u8(num); }
+constexpr auto operator "" _i8   (unsigned long long int num) noexcept -> i8    { return    u8(num); }
+constexpr auto operator "" _u16  (unsigned long long int num) noexcept -> u16   { return   u16(num); }
+constexpr auto operator "" _i16  (unsigned long long int num) noexcept -> i16   { return   i16(num); }
+constexpr auto operator "" _u32  (unsigned long long int num) noexcept -> u32   { return   u32(num); }
+constexpr auto operator "" _i32  (unsigned long long int num) noexcept -> i32   { return   i32(num); }
+constexpr auto operator "" _u64  (unsigned long long int num) noexcept -> u64   { return   u64(num); }
+constexpr auto operator "" _i64  (unsigned long long int num) noexcept -> i64   { return   i64(num); }
+constexpr auto operator "" _usize(unsigned long long int num) noexcept -> usize { return usize(num); }
+
+constexpr auto operator "" _c8 (char c) noexcept -> c8  { return  c8(c); }
+constexpr auto operator "" _c16(char c) noexcept -> c16 { return c16(c); }
+constexpr auto operator "" _c32(char c) noexcept -> c32 { return c32(c); }
+constexpr auto operator "" _c8 (unsigned long long int c) noexcept -> c8  { return  c8(c); }
+constexpr auto operator "" _c16(unsigned long long int c) noexcept -> c16 { return c16(c); }
+constexpr auto operator "" _c32(unsigned long long int c) noexcept -> c32 { return c32(c); }
+
+constexpr auto operator "" _f32(long double num) noexcept -> f32 { return (f32) num; }
+constexpr auto operator "" _f64(long double num) noexcept -> f64 { return (f64) num; }
diff --git a/2021/misc/types.hpp b/2021/misc/types.hpp
new file mode 100644
index 0000000..bc94dab
--- /dev/null
+++ b/2021/misc/types.hpp
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ *
+ * Copyright (c) 2020 Gnarwhal
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files(the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *******************************************************************************/
+
+#ifndef GNARWHAL_REDWOOD_TYPES
+#define GNARWHAL_REDWOOD_TYPES
+
+#include <cstddef>
+#include <cstdint>
+
+using u8    = std::uint8_t;
+using i8    = std::int8_t;
+using u16   = std::uint16_t;
+using i16   = std::int16_t;
+using u32   = std::uint32_t;
+using i32   = std::int32_t;
+using u64   = std::uint64_t;
+using i64   = std::int64_t;
+using usize = std::size_t;
+
+constexpr auto operator "" _u8   (unsigned long long int num) noexcept -> u8;
+constexpr auto operator "" _i8   (unsigned long long int num) noexcept -> i8;
+constexpr auto operator "" _u16  (unsigned long long int num) noexcept -> u16;
+constexpr auto operator "" _i16  (unsigned long long int num) noexcept -> i16;
+constexpr auto operator "" _u32  (unsigned long long int num) noexcept -> u32;
+constexpr auto operator "" _i32  (unsigned long long int num) noexcept -> i32;
+constexpr auto operator "" _u64  (unsigned long long int num) noexcept -> u64;
+constexpr auto operator "" _i64  (unsigned long long int num) noexcept -> i64;
+constexpr auto operator "" _usize(unsigned long long int num) noexcept -> usize;
+
+using c8  = u8;
+using c16 = u16;
+using c32 = u32;
+
+constexpr auto operator "" _c8 (char c) noexcept -> c8;
+constexpr auto operator "" _c16(char c) noexcept -> c16;
+constexpr auto operator "" _c32(char c) noexcept -> c32;
+constexpr auto operator "" _c8 (unsigned long long int c) noexcept -> c8;
+constexpr auto operator "" _c16(unsigned long long int c) noexcept -> c16;
+constexpr auto operator "" _c32(unsigned long long int c) noexcept -> c32;
+
+using f32 = float;
+using f64 = double;
+
+constexpr auto operator "" _f32(long double num) noexcept -> f32;
+constexpr auto operator "" _f64(long double num) noexcept -> f64;
+
+#endif // GNARWHAL_REDWOOD_TYPES