From 69de9551581f237a3d6f7287895022fe661e0bb7 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 15:00:04 +0100 Subject: [PATCH 01/37] Remove C++ solutions --- 2019/.gitignore | 1 - 2019/README.md | 31 ----- 2019/src/day01.cpp | 26 ---- 2019/src/day02.cpp | 36 ------ 2019/src/day03.cpp | 84 ------------- 2019/src/day04.cpp | 94 -------------- 2019/src/day05.cpp | 15 --- 2019/src/day06.cpp | 68 ---------- 2019/src/day07.cpp | 69 ----------- 2019/src/day08.cpp | 69 ----------- 2019/src/day09.cpp | 33 ----- 2019/src/day10.cpp | 118 ------------------ 2019/src/day11.cpp | 80 ------------ 2019/src/day12.cpp | 100 --------------- 2019/src/day13.cpp | 138 --------------------- 2019/src/day14.cpp | 146 ---------------------- 2019/src/day15.cpp | 153 ----------------------- 2019/src/day16.cpp | 117 ------------------ 2019/src/day17.cpp | 103 ---------------- 2019/src/day17/route-map.py | 76 ------------ 2019/src/day18.cpp | 226 ---------------------------------- 2019/src/day19.cpp | 89 ------------- 2019/src/day20.cpp | 215 -------------------------------- 2019/src/day21.cpp | 47 ------- 2019/src/day22.cpp | 149 ---------------------- 2019/src/day23.cpp | 10 -- 2019/src/day24.cpp | 188 ---------------------------- 2019/src/day25.cpp | 10 -- 2019/src/days.hpp | 57 --------- 2019/src/implementations.cpp | 35 ------ 2019/src/implementations.hpp | 9 -- 2019/src/point.hpp | 78 ------------ 2019/src/runner.cpp | 135 -------------------- 2019/src/utils.cpp | 191 ---------------------------- 2019/src/utils.hpp | 123 ------------------ 2019/tests/samples/.gitkeep | 1 - 2019/tests/samples/01-1-1.in | 1 - 2019/tests/samples/01-1-1.out | 1 - 2019/tests/samples/03-1-1.in | 2 - 2019/tests/samples/03-1-1.out | 1 - 2019/tests/samples/03-1-2.in | 2 - 2019/tests/samples/03-1-2.out | 1 - 2019/tests/samples/03-1-3.in | 2 - 2019/tests/samples/03-1-3.out | 1 - 2019/tests/samples/03-2-1.in | 1 - 2019/tests/samples/03-2-1.out | 1 - 2019/tests/samples/03-2-2.in | 1 - 2019/tests/samples/03-2-2.out | 1 - 2019/tests/samples/03-2-3.in | 1 - 2019/tests/samples/03-2-3.out | 1 - 2019/tests/samples/06-1-1.in | 11 -- 2019/tests/samples/06-1-1.out | 1 - 2019/tests/samples/06-2-1.in | 13 -- 2019/tests/samples/06-2-1.out | 1 - 2019/tests/samples/07-1-1.in | 1 - 2019/tests/samples/07-1-1.out | 1 - 2019/tests/samples/07-1-2.in | 2 - 2019/tests/samples/07-1-2.out | 1 - 2019/tests/samples/07-1-3.in | 2 - 2019/tests/samples/07-1-3.out | 1 - 2019/tests/samples/07-2-1.in | 2 - 2019/tests/samples/07-2-1.out | 1 - 2019/tests/samples/07-2-2.in | 3 - 2019/tests/samples/07-2-2.out | 1 - 2019/tests/samples/10-1-1.in | 5 - 2019/tests/samples/10-1-1.out | 1 - 2019/tests/samples/10-1-2.in | 10 -- 2019/tests/samples/10-1-2.out | 1 - 2019/tests/samples/10-1-3.in | 10 -- 2019/tests/samples/10-1-3.out | 1 - 2019/tests/samples/10-1-4.in | 10 -- 2019/tests/samples/10-1-4.out | 1 - 2019/tests/samples/10-1-5.in | 20 --- 2019/tests/samples/10-1-5.out | 1 - 2019/tests/samples/12-2-1.in | 4 - 2019/tests/samples/12-2-1.out | 1 - 2019/tests/samples/12-2-2.in | 4 - 2019/tests/samples/12-2-2.out | 1 - 2019/tests/samples/14-1-1.in | 6 - 2019/tests/samples/14-1-1.out | 1 - 2019/tests/samples/14-1-2.in | 7 -- 2019/tests/samples/14-1-2.out | 1 - 2019/tests/samples/14-1-3.in | 9 -- 2019/tests/samples/14-1-3.out | 1 - 2019/tests/samples/14-1-4.in | 12 -- 2019/tests/samples/14-1-4.out | 1 - 2019/tests/samples/14-1-5.in | 17 --- 2019/tests/samples/14-1-5.out | 1 - 2019/tests/samples/14-2-1.in | 1 - 2019/tests/samples/14-2-1.out | 1 - 2019/tests/samples/14-2-2.in | 1 - 2019/tests/samples/14-2-2.out | 1 - 2019/tests/samples/14-2-3.in | 1 - 2019/tests/samples/14-2-3.out | 1 - 2019/tests/samples/16-1-1.in | 1 - 2019/tests/samples/16-1-1.out | 1 - 2019/tests/samples/16-1-2.in | 1 - 2019/tests/samples/16-1-2.out | 1 - 2019/tests/samples/16-1-3.in | 1 - 2019/tests/samples/16-1-3.out | 1 - 2019/tests/samples/18-1-1.in | 3 - 2019/tests/samples/18-1-1.out | 1 - 2019/tests/samples/18-1-2.in | 5 - 2019/tests/samples/18-1-2.out | 1 - 2019/tests/samples/18-1-3.in | 5 - 2019/tests/samples/18-1-3.out | 1 - 2019/tests/samples/18-1-4.in | 9 -- 2019/tests/samples/18-1-4.out | 1 - 2019/tests/samples/18-1-5.in | 6 - 2019/tests/samples/18-1-5.out | 1 - 2019/tests/samples/18-2-1.in | 7 -- 2019/tests/samples/18-2-1.out | 1 - 2019/tests/samples/20-1-1.in | 19 --- 2019/tests/samples/20-1-1.out | 1 - 2019/tests/samples/20-1-2.in | 37 ------ 2019/tests/samples/20-1-2.out | 1 - 2019/tests/samples/20-2-2.in | 37 ------ 2019/tests/samples/20-2-2.out | 1 - 2019/tests/samples/24-1-1.in | 5 - 2019/tests/samples/24-1-1.out | 1 - 2019/tests/test_intcode.cpp | 78 ------------ 2019/tests/test_solutions.cpp | 110 ----------------- 122 files changed, 3647 deletions(-) delete mode 100644 2019/README.md delete mode 100644 2019/src/day01.cpp delete mode 100644 2019/src/day02.cpp delete mode 100644 2019/src/day03.cpp delete mode 100644 2019/src/day04.cpp delete mode 100644 2019/src/day05.cpp delete mode 100644 2019/src/day06.cpp delete mode 100644 2019/src/day07.cpp delete mode 100644 2019/src/day08.cpp delete mode 100644 2019/src/day09.cpp delete mode 100644 2019/src/day10.cpp delete mode 100644 2019/src/day11.cpp delete mode 100644 2019/src/day12.cpp delete mode 100644 2019/src/day13.cpp delete mode 100644 2019/src/day14.cpp delete mode 100644 2019/src/day15.cpp delete mode 100644 2019/src/day16.cpp delete mode 100644 2019/src/day17.cpp delete mode 100644 2019/src/day17/route-map.py delete mode 100644 2019/src/day18.cpp delete mode 100644 2019/src/day19.cpp delete mode 100644 2019/src/day20.cpp delete mode 100644 2019/src/day21.cpp delete mode 100644 2019/src/day22.cpp delete mode 100644 2019/src/day23.cpp delete mode 100644 2019/src/day24.cpp delete mode 100644 2019/src/day25.cpp delete mode 100644 2019/src/days.hpp delete mode 100644 2019/src/implementations.cpp delete mode 100644 2019/src/implementations.hpp delete mode 100644 2019/src/point.hpp delete mode 100644 2019/src/runner.cpp delete mode 100644 2019/src/utils.cpp delete mode 100644 2019/src/utils.hpp delete mode 100644 2019/tests/samples/.gitkeep delete mode 100644 2019/tests/samples/01-1-1.in delete mode 100644 2019/tests/samples/01-1-1.out delete mode 100644 2019/tests/samples/03-1-1.in delete mode 100644 2019/tests/samples/03-1-1.out delete mode 100644 2019/tests/samples/03-1-2.in delete mode 100644 2019/tests/samples/03-1-2.out delete mode 100644 2019/tests/samples/03-1-3.in delete mode 100644 2019/tests/samples/03-1-3.out delete mode 120000 2019/tests/samples/03-2-1.in delete mode 100644 2019/tests/samples/03-2-1.out delete mode 120000 2019/tests/samples/03-2-2.in delete mode 100644 2019/tests/samples/03-2-2.out delete mode 120000 2019/tests/samples/03-2-3.in delete mode 100644 2019/tests/samples/03-2-3.out delete mode 100644 2019/tests/samples/06-1-1.in delete mode 100644 2019/tests/samples/06-1-1.out delete mode 100644 2019/tests/samples/06-2-1.in delete mode 100644 2019/tests/samples/06-2-1.out delete mode 100644 2019/tests/samples/07-1-1.in delete mode 100644 2019/tests/samples/07-1-1.out delete mode 100644 2019/tests/samples/07-1-2.in delete mode 100644 2019/tests/samples/07-1-2.out delete mode 100644 2019/tests/samples/07-1-3.in delete mode 100644 2019/tests/samples/07-1-3.out delete mode 100644 2019/tests/samples/07-2-1.in delete mode 100644 2019/tests/samples/07-2-1.out delete mode 100644 2019/tests/samples/07-2-2.in delete mode 100644 2019/tests/samples/07-2-2.out delete mode 100644 2019/tests/samples/10-1-1.in delete mode 100644 2019/tests/samples/10-1-1.out delete mode 100644 2019/tests/samples/10-1-2.in delete mode 100644 2019/tests/samples/10-1-2.out delete mode 100644 2019/tests/samples/10-1-3.in delete mode 100644 2019/tests/samples/10-1-3.out delete mode 100644 2019/tests/samples/10-1-4.in delete mode 100644 2019/tests/samples/10-1-4.out delete mode 100644 2019/tests/samples/10-1-5.in delete mode 100644 2019/tests/samples/10-1-5.out delete mode 100644 2019/tests/samples/12-2-1.in delete mode 100644 2019/tests/samples/12-2-1.out delete mode 100644 2019/tests/samples/12-2-2.in delete mode 100644 2019/tests/samples/12-2-2.out delete mode 100644 2019/tests/samples/14-1-1.in delete mode 100644 2019/tests/samples/14-1-1.out delete mode 100644 2019/tests/samples/14-1-2.in delete mode 100644 2019/tests/samples/14-1-2.out delete mode 100644 2019/tests/samples/14-1-3.in delete mode 100644 2019/tests/samples/14-1-3.out delete mode 100644 2019/tests/samples/14-1-4.in delete mode 100644 2019/tests/samples/14-1-4.out delete mode 100644 2019/tests/samples/14-1-5.in delete mode 100644 2019/tests/samples/14-1-5.out delete mode 120000 2019/tests/samples/14-2-1.in delete mode 100644 2019/tests/samples/14-2-1.out delete mode 120000 2019/tests/samples/14-2-2.in delete mode 100644 2019/tests/samples/14-2-2.out delete mode 120000 2019/tests/samples/14-2-3.in delete mode 100644 2019/tests/samples/14-2-3.out delete mode 100644 2019/tests/samples/16-1-1.in delete mode 100644 2019/tests/samples/16-1-1.out delete mode 100644 2019/tests/samples/16-1-2.in delete mode 100644 2019/tests/samples/16-1-2.out delete mode 100644 2019/tests/samples/16-1-3.in delete mode 100644 2019/tests/samples/16-1-3.out delete mode 100644 2019/tests/samples/18-1-1.in delete mode 100644 2019/tests/samples/18-1-1.out delete mode 100644 2019/tests/samples/18-1-2.in delete mode 100644 2019/tests/samples/18-1-2.out delete mode 100644 2019/tests/samples/18-1-3.in delete mode 100644 2019/tests/samples/18-1-3.out delete mode 100644 2019/tests/samples/18-1-4.in delete mode 100644 2019/tests/samples/18-1-4.out delete mode 100644 2019/tests/samples/18-1-5.in delete mode 100644 2019/tests/samples/18-1-5.out delete mode 100644 2019/tests/samples/18-2-1.in delete mode 100644 2019/tests/samples/18-2-1.out delete mode 100644 2019/tests/samples/20-1-1.in delete mode 100644 2019/tests/samples/20-1-1.out delete mode 100644 2019/tests/samples/20-1-2.in delete mode 100644 2019/tests/samples/20-1-2.out delete mode 100644 2019/tests/samples/20-2-2.in delete mode 100644 2019/tests/samples/20-2-2.out delete mode 100644 2019/tests/samples/24-1-1.in delete mode 100644 2019/tests/samples/24-1-1.out delete mode 100644 2019/tests/test_intcode.cpp delete mode 100644 2019/tests/test_solutions.cpp diff --git a/2019/.gitignore b/2019/.gitignore index 8eee68f..e69de29 100644 --- a/2019/.gitignore +++ b/2019/.gitignore @@ -1 +0,0 @@ -cmake-build-* diff --git a/2019/README.md b/2019/README.md deleted file mode 100644 index f857611..0000000 --- a/2019/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Advent of Code 2019 - -This project contains my implementations for Advent of Code 2019. The -goal is to create reasonably fast C++ implementations in readable and -ergonomic C++. At the end of the contest, I will probably do a write- -up of some sorts. - - -## How to compile - -Install the dependencies: - -- [GTest](https://github.com/google/googletest) **Note:** this project - by default tries to dynamically link GTest, and the Ubuntu packages - only provide a statically linked archive. You may need to compile it - for yourself. - -``` -mkdir build && cd build -cmake .. -make -``` - -You can then use the generated executable `runner`. - -## Running tests - -Tests can be executed with `make test`. The `tests` folder contains a -`samples` folder. This folder contains pairs of `XX-Y-something.in` and -`XX-Y-something.out`, which will be taken as the expected input and -output of the implementations. You can add your own samples to this mix. diff --git a/2019/src/day01.cpp b/2019/src/day01.cpp deleted file mode 100644 index 457d8a8..0000000 --- a/2019/src/day01.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include "days.hpp" - -static inline int required(int weight) { - return weight / 3 - 2; -} - -void aoc2019::day01_part1(std::istream &input, std::ostream &output) { - int total = 0; - for (int current; input >> current;) { - total += required(current); - } - - output << total << std::endl; -} - -void aoc2019::day01_part2(std::istream &input, std::ostream &output) { - int total = 0; - for (int current; input >> current;) { - for (int fuel = required(current); fuel > 0; fuel = required(fuel)) { - total += fuel; - } - } - - output << total << std::endl; -} diff --git a/2019/src/day02.cpp b/2019/src/day02.cpp deleted file mode 100644 index d251264..0000000 --- a/2019/src/day02.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" - -static int run_program(std::vector program) { - aoc2019::IntCodeComputer computer(std::move(program)); - computer.run(); - - return computer[0]; -} - -void aoc2019::day02_part1(std::istream &input, std::ostream &output) { - auto program = IntCodeComputer::read_intcode(input); - program[1] = 12; - program[2] = 2; - output << run_program(std::move(program)) << std::endl; -} - -void aoc2019::day02_part2(std::istream &input, std::ostream &output) { - auto program = IntCodeComputer::read_intcode(input); - - for (int noun = 0; noun < 100; ++noun) { - for (int verb = 0; verb < 100; ++verb) { - program[1] = noun; - program[2] = verb; - if (run_program(program) == 19690720) { - output << 100 * noun + verb << std::endl; - return; - } - } - } - throw std::domain_error("No valid solution."); -} diff --git a/2019/src/day03.cpp b/2019/src/day03.cpp deleted file mode 100644 index f618c7a..0000000 --- a/2019/src/day03.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "days.hpp" -#include "point.hpp" -#include "utils.hpp" - -namespace { - typedef aoc2019::Point point_t; - - const std::unordered_map DIRECTION_MAP = { - {'U', {0, -1}}, - {'D', {0, 1}}, - {'L', {-1, 0}}, - {'R', {1, 0}}, - }; - - std::unordered_map get_points(std::string_view line) { - std::unordered_map points{}; - point_t pos = {}; - - int steps = 0; - for (auto entry = aoc2019::strtok(line); !line.empty() || !entry.empty(); entry = aoc2019::strtok(line)) { - const auto dir = DIRECTION_MAP.at(entry[0]); - std::size_t amount = 0; - aoc2019::from_chars(entry.substr(1), amount); - assert(amount > 0 && "Must have some valid direction"); - - for (std::size_t i = 0; i < amount; ++i) { - ++steps; - pos += dir; - if (!points.count(pos)) { - points[pos] = steps; - } - } - } - - return points; - } - - std::pair, std::unordered_map> read_input(std::istream& input) { - std::string buffer; - std::getline(input, buffer); - auto a = get_points(buffer); - std::getline(input, buffer); - auto b = get_points(buffer); - - return { std::move(a), std::move(b) }; - } -} - -void aoc2019::day03_part1(std::istream &input, std::ostream &output) { - auto [a, b] = read_input(input); - - int best = std::numeric_limits::max(); - - for (const auto& point : a) { - if (b.count(point.first) && point.first.l1() < best) { - best = point.first.l1(); - } - } - - output << best << std::endl; -} - -void aoc2019::day03_part2(std::istream &input, std::ostream &output) { - auto [a, b] = read_input(input); - - int best = std::numeric_limits::max(); - - for (const auto& ap : a) { - const auto bp = b.find(ap.first); - - if (bp != b.cend() && (ap.second + bp->second) < best) { - best = ap.second + bp->second; - } - } - - output << best << std::endl; -} diff --git a/2019/src/day04.cpp b/2019/src/day04.cpp deleted file mode 100644 index a8dd0b2..0000000 --- a/2019/src/day04.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include "days.hpp" - -namespace { - constexpr bool is_valid_pass(int num) { - bool has_double = false; - int prev = 11; - - for (; num != 0; num /= 10) { - int digit = num % 10; - - if (digit == prev) { - has_double = true; - } - - if (digit > prev) { - return false; - } - - prev = digit; - } - - return has_double; - } - - constexpr bool is_valid_pass2(int num) { - int prev = 11; - bool has_double = false; - int run = 1; - - for (; num != 0; num /= 10) { - int digit = num % 10; - - if (digit == prev) { - ++run; - } else { - if (run == 2) { - has_double = true; - } - run = 1; - } - - if (digit > prev) { - return false; - } - - prev = digit; - } - - return has_double || run == 2; - } - - std::pair read_input(std::istream& input) { - int a, b; - input >> a; - input.ignore(); - input >> b; - - return {a, b}; - } -} - -void aoc2019::day04_part1(std::istream &input, std::ostream &output) { - auto [start_range, end_range] = read_input(input); - - int num_valid = 0; - for (; start_range <= end_range; ++start_range) { - num_valid += is_valid_pass(start_range); - } - - output << num_valid << std::endl; -} - -void aoc2019::day04_part2(std::istream &input, std::ostream &output) { - auto [start_range, end_range] = read_input(input); - - int num_valid = 0; - for (; start_range <= end_range; ++start_range) { - num_valid += is_valid_pass2(start_range); - } - - output << num_valid << std::endl; -} - -// Poor man's unit tests -static_assert(is_valid_pass(122345)); -static_assert(is_valid_pass(111111)); -static_assert(!is_valid_pass(223450)); -static_assert(!is_valid_pass(123678)); - -static_assert(is_valid_pass2(112233)); -static_assert(!is_valid_pass2(123444)); -static_assert(is_valid_pass2(111122)); diff --git a/2019/src/day05.cpp b/2019/src/day05.cpp deleted file mode 100644 index aaa749d..0000000 --- a/2019/src/day05.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include "days.hpp" -#include "utils.hpp" - -void aoc2019::day05_part1(std::istream &input, std::ostream &output) { - auto program = IntCodeComputer::read_intcode(input); - auto result = run_intcode(program, { 1 }); - output << result.back() << std::endl; -} - -void aoc2019::day05_part2(std::istream &input, std::ostream &output) { - auto program = IntCodeComputer::read_intcode(input); - auto result = run_intcode(program, { 5 }); - output << result.back() << std::endl; -} diff --git a/2019/src/day06.cpp b/2019/src/day06.cpp deleted file mode 100644 index 8ea162a..0000000 --- a/2019/src/day06.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include -#include -#include "days.hpp" - -namespace { - std::vector> read_orbits(std::istream &input) { - std::vector> result; - std::string name1, name2; - - while (std::getline(input, name1, ')')) { - std::getline(input, name2); - - result.emplace_back(name1, name2); - } - - return result; - } -} - -void aoc2019::day06_part1(std::istream &input, std::ostream &output) { - std::unordered_map> orbits; - - for (auto[a, b] : read_orbits(input)) { - orbits[std::move(a)].emplace_back(std::move(b)); - } - - std::deque> todo = {{"COM", 0}}; - int total_orbits = 0; - - while (!todo.empty()) { - auto[name, offset] = todo.front(); - todo.pop_front(); - - total_orbits += offset; - - for (const auto& partner : orbits[name]) { - todo.emplace_back(partner, offset + 1); - } - } - - output << total_orbits << std::endl; -} - -void aoc2019::day06_part2(std::istream &input, std::ostream &output) { - std::unordered_map ancestors; - - for (auto[a, b] : read_orbits(input)) { - ancestors[std::move(b)] = std::move(a); - } - - std::unordered_map santa_ancestors; - - for (auto current = ancestors["SAN"]; current != "COM"; current = ancestors[current]) { - santa_ancestors[ancestors[current]] = santa_ancestors[current] + 1; - } - - int dist = 0; - for (auto current = ancestors["YOU"]; current != "COM"; current = ancestors[current], ++dist) { - if (auto it = santa_ancestors.find(current); it != santa_ancestors.end()) { - output << dist + it->second << std::endl; - return; - } - } - - throw std::domain_error("No valid path."); -} diff --git a/2019/src/day07.cpp b/2019/src/day07.cpp deleted file mode 100644 index cc57b1e..0000000 --- a/2019/src/day07.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" - -namespace { - using aoc2019::IntCodeComputer; - - std::int64_t simulate(const std::vector &program, const std::array &phases) { - std::int64_t state = 0; - for (auto phase : phases) { - std::deque outputs; - IntCodeComputer computer{program, {phase, state}}; - computer.connectOutput(outputs); - computer.run(); - state = outputs.front(); - } - - return state; - } - - int simulate2(const std::vector &program, const std::array &phases) { - std::vector computers; - for (int phase : phases) { - computers.emplace_back(program, std::deque{phase}); - } - - for (int i = 0; i < computers.size(); ++i) { - computers[i].connectOutput(computers[(i + 1) % 5]); - } - - computers[0].sendInput(0); - - while (std::any_of(computers.begin(), computers.end(), [](const auto &c) { return !c.isTerminated();})) { - for (auto& computer : computers) { - computer.run(); - } - } - - return computers[0].currentInputs().back(); - } -} - -void aoc2019::day07_part1(std::istream &input, std::ostream &output) { - const auto program = aoc2019::IntCodeComputer::read_intcode(input); - std::array phases{0, 1, 2, 3, 4}; - - std::int64_t best = 0; - - do { - best = std::max(simulate(program, phases), best); - } while (std::next_permutation(phases.begin(), phases.end())); - - output << best << std::endl; -} - -void aoc2019::day07_part2(std::istream &input, std::ostream &output) { - const auto program = aoc2019::IntCodeComputer::read_intcode(input); - std::array phases{5, 6, 7, 8, 9}; - - int best = 0; - - do { - best = std::max(simulate2(program, phases), best); - } while (std::next_permutation(phases.begin(), phases.end())); - - output << best << std::endl; -} diff --git a/2019/src/day08.cpp b/2019/src/day08.cpp deleted file mode 100644 index 4c6c0e0..0000000 --- a/2019/src/day08.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include -#include "days.hpp" - -namespace { - constexpr std::size_t WIDTH = 25; - constexpr std::size_t HEIGHT = 6; - constexpr std::size_t TILE_SIZE = WIDTH * HEIGHT; - - enum Color { - BLACK = '0', - WHITE = '1', - TRANSPARENT = '2', - }; -} - - -void aoc2019::day08_part1(std::istream &input, std::ostream &output) { - std::string buffer; - std::getline(input, buffer); - - std::string_view image = buffer; - auto best = std::numeric_limits::max(); - auto best_score = 0; - - for (std::size_t i = 0; i < buffer.length(); i += TILE_SIZE) { - auto tile = image.substr(i, TILE_SIZE); - - auto zeros = std::count(tile.begin(), tile.end(), '0'); - - if (zeros < best) { - best = zeros; - - best_score = std::count(tile.begin(), tile.end(), '1') * std::count(tile.begin(), tile.end(), '2'); - } - } - - output << best_score << std::endl; -} - -void aoc2019::day08_part2(std::istream &input, std::ostream &output) { - std::string buffer; - std::getline(input, buffer); - - std::string_view image = buffer; - - std::array final_image; - std::fill(final_image.begin(), final_image.end(), TRANSPARENT); - - for (std::size_t i = 0; i < buffer.length(); i += TILE_SIZE) { - auto tile = image.substr(i, TILE_SIZE); - - for (int j = 0; j < TILE_SIZE; ++j) { - if (final_image[j] == TRANSPARENT) { - final_image[j] = static_cast(tile[j]); - } - } - } - - for (std::size_t i = 0; i < final_image.size(); ++i) { - output << (final_image[i] == WHITE ? '#' : ' '); - if (i % WIDTH == WIDTH - 1) { - output << '\n'; - } - } -} diff --git a/2019/src/day09.cpp b/2019/src/day09.cpp deleted file mode 100644 index d1721ad..0000000 --- a/2019/src/day09.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include "days.hpp" -#include "utils.hpp" - -void aoc2019::day09_part1(std::istream &input, std::ostream &output) { - std::deque outputs; - - IntCodeComputer computer(input, { 1 }); - computer.connectOutput(outputs); - - computer.run(); - - if (outputs.size() != 1) { - std::cerr << "Error: " << outputs.size() << std::endl; - for (auto c : outputs) { - std::cerr << c << std::endl; - } - } else { - output << outputs.front() << std::endl; - } -} - -void aoc2019::day09_part2(std::istream &input, std::ostream &output) { - std::deque outputs; - - IntCodeComputer computer(input, { 2 }); - computer.connectOutput(outputs); - - computer.run(); - - output << outputs.front() << std::endl; -} diff --git a/2019/src/day10.cpp b/2019/src/day10.cpp deleted file mode 100644 index f08a48d..0000000 --- a/2019/src/day10.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include -#include -#include -#include "days.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - - std::vector read_points(std::istream &input) { - std::vector result; - - int y = 0; - - for (std::string buffer; std::getline(input, buffer); ++y) { - std::size_t x = 0; - - while ((x = buffer.find('#', x)) != std::string::npos) { - result.push_back({(int) x, y}); - x += 1; - } - } - - return result; - } - - point_t simplify(point_t x) { - auto gcd = std::abs(std::gcd(x[0], x[1])); - if (gcd > 1) { - return {x[0] / gcd, x[1] / gcd}; - } - - return x; - } - - std::pair part1(const std::vector &points) { - std::size_t best = 0; - std::size_t best_index = 0; - std::unordered_set visible; - - for (std::size_t i = 0; i < points.size(); ++i) { - visible.clear(); - - const auto point = points[i]; - - for (auto asteroid : points) { - if (asteroid == point) continue; - visible.insert(simplify(asteroid - point)); - } - - if (visible.size() > best) { - best = visible.size(); - best_index = i; - } - - best = std::max(visible.size(), best); - } - - return {best, best_index}; - } -} - -void aoc2019::day10_part1(std::istream &input, std::ostream &output) { - const auto points = read_points(input); - - auto[best, _] = part1(points); - - output << best << std::endl; -} - -void aoc2019::day10_part2(std::istream &input, std::ostream &output) { - const auto points = read_points(input); - const auto[_, base] = part1(points); - const auto base_point = points[base]; - - std::unordered_map> angle_points; - - for (auto point : points) { - if (point == base_point) continue; - auto diff = point - base_point; - - angle_points[simplify(diff)].push_back(diff); - } - - std::vector> angles; - - for (auto &entry : angle_points) { - angles.emplace_back(std::atan2(entry.first[1], entry.first[0]), entry.first); - // Sort entries in descending order of distance so we can pop_back() them - std::sort(entry.second.begin(), entry.second.end(), [](auto a, auto b) { return a.l1() > b.l1(); }); - } - - std::sort(angles.begin(), angles.end(), std::greater<>{}); - - const auto starting_point = std::make_pair(float(0.5 * M_PI), - point_t{std::numeric_limits::max(), - std::numeric_limits::max()}); - - auto it = std::lower_bound(angles.begin(), angles.end(), starting_point, std::greater<>{}); - - for (int hits = 0; hits < 199; ++hits) { - angle_points[it->second].pop_back(); - - // Advance it to the next asteroid we can hit. - while (angle_points[it->second].empty()) { - ++it; - if (it == angles.end()) { - it = angles.begin(); - } - } - } - - auto final_asteroid = angle_points[it->second].back() + base_point; - - output << final_asteroid[0] * 100 + final_asteroid[1] << std::endl; -} diff --git a/2019/src/day11.cpp b/2019/src/day11.cpp deleted file mode 100644 index 21fb882..0000000 --- a/2019/src/day11.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include "days.hpp" -#include "utils.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - using aoc2019::IntCodeComputer; - - inline point_t turn_right(point_t direction) { - return {-direction[1], direction[0]}; - } - - inline point_t turn_left(point_t direction) { - return {direction[1], -direction[0]}; - } - - std::unordered_map simulate(std::istream &input, bool background = false) { - std::unordered_map image; - - point_t direction{0, -1}; - point_t pos = {0, 0}; - - IntCodeComputer computer(IntCodeComputer::read_intcode(input), {}); - std::deque outputs; - - computer.connectOutput(outputs); - - while (!computer.isTerminated()) { - const auto it = image.find(pos); - computer.sendInput(it != image.end() ? it->second : background); - computer.run(); - - if (!outputs.empty()) { - assert(outputs.size() == 2); - auto color = outputs.front(); - auto turn = outputs.back(); - outputs.clear(); - - image[pos] = color; - - if (turn) { - direction = turn_right(direction); - } else { - direction = turn_left(direction); - } - - pos += direction; - } - } - - return image; - } -} - -void aoc2019::day11_part1(std::istream &input, std::ostream &output) { - const auto result = simulate(input); - - output << result.size() << std::endl; -} - -void aoc2019::day11_part2(std::istream &input, std::ostream &output) { - const auto result = simulate(input, true); - - // Determine bounding box - auto[lower,upper] = aoc2019::bounding_box(result); - - for (int y = lower[1]; y <= upper[1]; ++y) { - for (int x = lower[0]; x <= upper[0]; ++x) { - if (auto it = result.find({x, y}); it != result.end() && it->second) { - output << '#'; - } else { - output << ' '; - } - } - - output << '\n'; - } -} diff --git a/2019/src/day12.cpp b/2019/src/day12.cpp deleted file mode 100644 index f1340bf..0000000 --- a/2019/src/day12.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include "days.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - using aoc2019::from_chars; - - std::vector read_moons(std::istream &input) { - std::vector moons; - - point_t moon; - - while (aoc2019::read_line_numbers_and_garbage(input, moon.begin())) { - moons.push_back(moon); - } - - return moons; - } - - void update_velocity(const point_t &a, point_t &va, const point_t &b, point_t &vb) { - for (int i = 0; i < a.size(); ++i) { - if (a[i] < b[i]) { - va[i]++; - vb[i]--; - } else if (a[i] > b[i]) { - va[i]--; - vb[i]++; - } - } - } - - void update_velocities(const std::vector &positions, std::vector &velocities) { - for (int i = 0; i < positions.size(); ++i) { - for (int j = i + 1; j < positions.size(); ++j) { - update_velocity(positions[i], velocities[i], positions[j], velocities[j]); - } - } - } - - void simulate_step(std::vector &moons, std::vector &velocities) { - update_velocities(moons, velocities); - - for (int j = 0; j < moons.size(); ++j) { - moons[j] += velocities[j]; - } - } -} - -void aoc2019::day12_part1(std::istream &input, std::ostream &output) { - auto moons = read_moons(input); - std::vector velocities(moons.size()); - - for (int i = 0; i < 1000; ++i) { - simulate_step(moons, velocities); - } - - int energy = 0; - - for (int i = 0; i < moons.size(); ++i) { - energy += moons[i].l1() * velocities[i].l1(); - } - - output << energy << std::endl; -} - -void aoc2019::day12_part2(std::istream &input, std::ostream &output) { - const auto moons = read_moons(input); - auto moons_mut = moons; - std::vector velocities(moons.size()); - - std::array recurrence = {0, 0, 0}; - - std::uint64_t steps = 0; - - while (!std::all_of(recurrence.begin(), recurrence.end(), [](auto x) { return x > 0; })) { - simulate_step(moons_mut, velocities); - ++steps; - - for (int i = 0; i < 3; ++i) { - if (!recurrence[i]) { - bool back_again = - std::all_of(velocities.begin(), velocities.end(), [i](const auto &x) { return !x[i]; }) - && std::equal(moons_mut.begin(), moons_mut.end(), moons.begin(), - [i](const auto &a, const auto &b) { - return a[i] == b[i]; - }); - - if (back_again) { - recurrence[i] = steps; - } - } - } - } - - auto result = std::lcm(recurrence[0], std::lcm(recurrence[1], recurrence[2])); - output << result << std::endl; -} diff --git a/2019/src/day13.cpp b/2019/src/day13.cpp deleted file mode 100644 index f8625e6..0000000 --- a/2019/src/day13.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include -#ifdef ANIMATE_DAY13 -#include -#include -#endif -#include "days.hpp" -#include "utils.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - - enum class Tile { - EMPTY, - WALL, - BLOCK, - PADDLE, - BALL, - }; - - typedef std::unordered_map Screen; - - std::optional update_screen(std::deque &output_buffer, Screen &screen) { - std::optional score; - while (!output_buffer.empty()) { - auto x = output_buffer.front(); output_buffer.pop_front(); - auto y = output_buffer.front(); output_buffer.pop_front(); - auto type = output_buffer.front(); output_buffer.pop_front(); - - if (x == -1 && y == 0) { - score = type; - continue; - } - - screen[{x, y}] = static_cast(type); - } - return score; - } - - void draw_screen(const Screen &screen, std::ostream& output) { - // Determine bounding box - using limits = std::numeric_limits; - - const auto [lower, upper] = aoc2019::bounding_box(screen); - - for (auto y = lower[1]; y <= upper[1]; ++y) { - for (auto x = lower[0]; x <= upper[0]; ++x) { - char c = ' '; - if (auto it = screen.find({x, y}); it != screen.end()) { - switch (it->second) { - case Tile::EMPTY: - c = ' '; - break; - - case Tile::BALL: - c = '*'; - break; - - case Tile::BLOCK: - c = '='; - break; - - case Tile::PADDLE: - c = '_'; - break; - - case Tile::WALL: - c = '#'; - break; - } - } - - output << c; - } - - output << '\n'; - } - } - - auto find_pos(const Screen &screen, Tile to_find) { - return std::find_if(screen.begin(), screen.end(), [to_find](const auto& x) { - return x.second == to_find; - }); - } -} - -void aoc2019::day13_part1(std::istream &input, std::ostream &output) { - Screen screen; - aoc2019::IntCodeComputer computer(aoc2019::IntCodeComputer::read_intcode(input)); - std::deque output_buffer; - computer.connectOutput(output_buffer); - computer.run(); - update_screen(output_buffer, screen); - - output << std::count_if(screen.begin(), screen.end(), [](const auto &x) { return x.second == Tile::BLOCK; }) - << std::endl; -} - -void aoc2019::day13_part2(std::istream &input, std::ostream &output) { - auto program = aoc2019::IntCodeComputer::read_intcode(input); - program[0] = 2; - - aoc2019::IntCodeComputer computer(std::move(program)); - std::deque output_buffer; - computer.connectOutput(output_buffer); - computer.run(); - - Screen screen; - - std::int64_t score = 0; - - while (!computer.isTerminated()) { - computer.run(); - auto new_score = update_screen(output_buffer, screen); - if (new_score) { - score = *new_score; - } - -#ifdef ANIMATE_DAY13 - output << "Score: " << score << std::endl; - draw_screen(screen, output); - std::this_thread::sleep_for(std::chrono::milliseconds(40)); -#endif - - auto ball_pos = find_pos(screen, Tile::BALL)->first; - auto paddle_pos = find_pos(screen, Tile::PADDLE)->first; - - if (ball_pos[0] < paddle_pos[0]) { - computer.sendInput(-1); - } else if (ball_pos[0] > paddle_pos[0]) { - computer.sendInput(1); - } else { - computer.sendInput(0); - } - } - - output << score << std::endl; -} diff --git a/2019/src/day14.cpp b/2019/src/day14.cpp deleted file mode 100644 index 2abebfd..0000000 --- a/2019/src/day14.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" - -namespace { - typedef std::pair requirement_t; - typedef std::vector reqlist_t; - - std::map read_recipes(std::istream &input) { - std::map recipes; - - std::string buffer; - std::regex listing_regex("(\\d+) ([A-Z]+)"); - - std::int64_t amount; - - while (std::getline(input, buffer)) { - reqlist_t requirements, production; - - std::string_view line = buffer; - - auto split_point = line.find(" => "); - - auto requirements_part = line.substr(0, split_point); - auto production_part = line.substr(split_point + 4); - - for (auto it = std::regex_token_iterator(requirements_part.begin(), requirements_part.end(), listing_regex, - {1, 2}); it != std::cregex_token_iterator(); ++it) { - std::from_chars(it->first, it->second, amount); - ++it; - - requirements.emplace_back(*it, amount); - } - - for (auto it = std::regex_token_iterator(production_part.begin(), production_part.end(), listing_regex, - {1, 2}); it != std::cregex_token_iterator(); ++it) { - std::from_chars(it->first, it->second, amount); - ++it; - - production.emplace_back(*it, amount); - } - - recipes[std::move(production)] = std::move(requirements); - } - - return recipes; - } - - template - std::unordered_map element_creators(const Map &map) { - std::unordered_map inverted; - - for (auto &entry : map) { - for (auto &x : entry.first) { - inverted[x.first] = entry.first; - } - } - - return inverted; - } - - std::vector topological_order(const std::map &recipes) { - std::vector order; - - std::unordered_map> edges; - for (auto &entry : recipes) { - for (auto &production : entry.first) { - std::transform(entry.second.begin(), entry.second.end(), std::back_inserter(edges[production.first]), - [](const auto &x) { - return x.first; - }); - } - } - - return aoc2019::topological_sort(edges); - } - - std::int64_t ore_to_fuel(const std::map &recipes, std::int64_t amount = 1) { - auto inverted = element_creators(recipes); - auto order = topological_order(recipes); - - std::unordered_map total_requirements; - total_requirements["FUEL"] = amount; - - for (const auto &element : order) { - if (element == "ORE") { - break; - } - - const auto number_required = total_requirements[element]; - if (number_required <= 0) { - continue; - } - - const auto &productions = inverted.at(element); - const auto &requirements = recipes.at(productions); - - auto number_produced = std::find_if(productions.begin(), productions.end(), - [element](const auto &x) { return x.first == element; })->second; - - auto productions_needed = number_required / number_produced + (number_required % number_produced ? 1 : 0); - - for (auto &requirement : requirements) { - total_requirements[requirement.first] += requirement.second * productions_needed; - } - - for (auto &production : productions) { - total_requirements[production.first] -= productions_needed * production.second; - } - } - - return total_requirements["ORE"]; - } -} - -void aoc2019::day14_part1(std::istream &input, std::ostream &output) { - auto recipes = read_recipes(input); - - output << ore_to_fuel(recipes) << std::endl; -} - -void aoc2019::day14_part2(std::istream &input, std::ostream &output) { - auto recipes = read_recipes(input); - - constexpr std::int64_t ore_stock = 1000000000000; - - std::int64_t min = 1, max = ore_stock + 1; // assumption: 1 ore produces < 1 fuel. - while (max - min > 1) { - auto cur = (max + min) / 2; - - if (ore_to_fuel(recipes, cur) < ore_stock) { - min = cur; - } else { - max = cur - 1; - } - } - - output << (max + min) / 2 << std::endl; -} diff --git a/2019/src/day15.cpp b/2019/src/day15.cpp deleted file mode 100644 index 8c0d90b..0000000 --- a/2019/src/day15.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - - enum class Tile { - Wall, - Empty, - Oxygen, - }; - - enum class Mark { - None, - Temp, - Permanent, - }; - - const std::unordered_map DIRECTIONS{ - {{0, -1}, 1}, - {{0, 1}, 2}, - {{-1, 0}, 3}, - {{1, 0}, 4}, - }; - - std::unordered_map read_map(std::istream &input) { - aoc2019::IntCodeComputer computer(input); - std::deque output_buffer; - computer.connectOutput(output_buffer); - - point_t pos = {0, 0}; - std::deque prev; - std::unordered_map map{{pos, Tile::Empty}}; - std::unordered_map markings{{pos, Mark::Temp}}; - - computer.run(); - - while (true) { - std::optional next_step; - - for (auto &direction : DIRECTIONS) { - if (markings[pos + direction.first] == Mark::None) { - next_step = direction.first; - break; - } - } - - if (next_step) { - const auto next_pos = pos + *next_step; - computer.sendInput(DIRECTIONS.at(*next_step)); - computer.run(); - - assert(!output_buffer.empty()); - - switch (output_buffer.front()) { - case 0: - markings[next_pos] = Mark::Permanent; - map[next_pos] = Tile::Wall; - break; - - case 1: - case 2: - prev.push_front(pos); - markings[next_pos] = Mark::Temp; - map[next_pos] = static_cast(output_buffer.front()); - pos = next_pos; - break; - - default: - throw std::domain_error("Invalid data from remote"); - } - output_buffer.pop_front(); - assert(output_buffer.empty()); - } else { - markings[pos] = Mark::Permanent; - // Nowhere left to go, move back. - if (prev.empty()) { - return map; - } - - auto prev_pos = prev.front(); - auto step = DIRECTIONS.at(prev_pos - pos); - prev.pop_front(); - computer.sendInput(step); - computer.run(); - // We should be able to travel back - assert(output_buffer.front() == 1); - output_buffer.pop_front(); - pos = prev_pos; - } - } - } - - template - int bfs(const std::unordered_map &map, point_t starting_point, Callback callback) { - std::deque> todo{{starting_point, 0}}; - std::unordered_set visited{{0, 0}}; - - int max_dist = 0; - - while (!todo.empty()) { - auto[cur, dist] = todo.front(); - todo.pop_front(); - - max_dist = std::max(max_dist, dist); - - for (auto &dir : DIRECTIONS) { - auto new_pos = cur + dir.first; - if (!visited.count(new_pos)) { - visited.insert(new_pos); - - if (callback(map.at(new_pos))) { - return dist + 1; - } - - switch (map.at(new_pos)) { - case Tile::Oxygen: - case Tile::Empty: - todo.emplace_back(new_pos, dist + 1); - break; - - default: - break; - } - } - } - } - - return max_dist; - } -} - -void aoc2019::day15_part1(std::istream &input, std::ostream &output) { - const auto map = read_map(input); - - auto dist = bfs(map, {0, 0}, [](Tile x) { return x == Tile::Oxygen; }); - - output << dist << std::endl; -} - -void aoc2019::day15_part2(std::istream &input, std::ostream &output) { - const auto map = read_map(input); - - auto starting_point = std::find_if(map.begin(), map.end(), [](auto &x) { return x.second == Tile::Oxygen; })->first; - - auto dist = bfs(map, starting_point, [](Tile x) { return false; }); - - output << dist << std::endl; -} diff --git a/2019/src/day16.cpp b/2019/src/day16.cpp deleted file mode 100644 index 5f83a32..0000000 --- a/2019/src/day16.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" - -namespace { - std::array base_pattern{0, 1, 0, -1}; - - int get_modifier(int rank, int pos) { - pos += 1; - pos /= rank + 1; - - return base_pattern[pos % 4]; - } - - std::vector read_input(std::istream &input) { - std::vector result; - - for (char c; input >> c;) { - assert(std::isdigit(c)); - result.push_back(c - '0'); - } - - return result; - } - - void simulate(std::vector numbers, std::ostream &output) { - std::vector new_numbers(numbers.size()); - std::vector partial_sums(numbers.size()); - - for (int i = 0; i < 100; ++i) { - for (int rank = 0; rank < numbers.size(); ++rank) { - std::partial_sum(numbers.begin() + rank, numbers.end(), partial_sums.begin() + rank); - int n = 0; - for (int pos = rank; pos < numbers.size(); pos += rank + 1) { - int run = std::min(rank + 1, (int) numbers.size() - pos); - if (int modifier = get_modifier(rank, pos); modifier) { - n += modifier * (partial_sums[pos + run - 1] - partial_sums[pos] + numbers[pos]); - } - } - - n = std::abs(n % 10); - - new_numbers[rank] = n; - } - - std::swap(numbers, new_numbers); - } - - std::copy(numbers.begin(), numbers.begin() + 8, std::ostream_iterator(output)); - output << std::endl; - } - - int get_offset(const std::vector &numbers) { - int offset = 0; - for (int i = 0; i < 7; ++i) { - offset *= 10; - offset += numbers[i]; - } - - return offset; - } - - std::vector numbers_from_offset(const std::vector &numbers, unsigned int offset) { - constexpr auto repetitions = 10000; - const auto desired_length = repetitions * numbers.size() - offset; - - std::vector numbers_after; - numbers_after.reserve(desired_length); - numbers_after.insert(numbers_after.end(), numbers.begin() + (offset % numbers.size()), numbers.end()); - - while (numbers_after.size() < desired_length) { - auto remaining = desired_length - numbers_after.size(); - if (remaining >= numbers.size()) { - numbers_after.insert(numbers_after.end(), numbers.begin(), numbers.end()); - } else { - numbers_after.insert(numbers_after.end(), numbers.begin(), numbers.end() + remaining); - } - } - - return numbers_after; - } -} - -void aoc2019::day16_part1(std::istream &input, std::ostream &output) { - auto numbers = read_input(input); - - simulate(std::move(numbers), output); -} - -void aoc2019::day16_part2(std::istream &input, std::ostream &output) { - auto numbers = read_input(input); - - const int offset = get_offset(numbers); - - numbers = numbers_from_offset(numbers, offset); - - std::vector new_numbers(numbers.size()); - std::vector partial_sums(numbers.size()); - - for (int i = 0; i < 100; ++i) { - std::partial_sum(numbers.rbegin(), numbers.rend(), partial_sums.rbegin()); - - std::transform(partial_sums.begin(), partial_sums.end(), new_numbers.begin(), [](int x) { - return x % 10; - }); - - std::swap(numbers, new_numbers); - } - - std::copy(numbers.begin(), numbers.begin() + 8, std::ostream_iterator(output)); - output << std::endl; -} diff --git a/2019/src/day17.cpp b/2019/src/day17.cpp deleted file mode 100644 index 3252eb1..0000000 --- a/2019/src/day17.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - - const std::unordered_map DIRECTIONS{ - {'^', {0, -1}}, - {'>', {0, 1}}, - {'v', {1, 0}}, - {'<', {-1, 0}}, - }; - - std::unordered_map read_scaffold(const std::deque &data) { - int x = 0; - int y = 0; - std::unordered_map map; - for (auto n : data) { - if (n == '\n') { - if (x == 0) { - // Double newline, end of map - break; - } - ++y; - x = 0; - continue; - } else { - map[{x, y}] = (char) n; - ++x; - } - } - - return map; - } -} - -void aoc2019::day17_part1(std::istream &input, std::ostream &output) { - IntCodeComputer computer(input); - std::deque output_buffer; - computer.connectOutput(output_buffer); - - computer.run(); - - const auto map = read_scaffold(output_buffer); - - std::int64_t total = 0; - - for (auto &entry : map) { - if (entry.second == '.') continue; - - bool is_intersection = std::all_of(DIRECTIONS.begin(), DIRECTIONS.end(), [&map, &entry](auto &x) { - auto it = map.find(x.second + entry.first); - return it != map.end() && it->second != '.'; - }); - - if (is_intersection) { - total += entry.first[0] * entry.first[1]; - } - } - - output << total << std::endl; -} - -void aoc2019::day17_part2(std::istream &input, std::ostream &output) { - using namespace std::literals; - - aoc2019::IntCodeComputer computer(input); - computer[0] = 2; - std::deque output_buffer; - computer.connectOutput(output_buffer); - - std::array programs = { - "L,6,R,8,L,4,R,8,L,12\n", - "L,12,R,10,L,4\n", - "L,12,L,6,L,4,L,4\n", - }; - - auto combined_programs = "A,B,B,C,B,C,B,C,A,A\n"sv; - - computer.sendInputs(combined_programs); - - for (auto program : programs) { - computer.sendInputs(program); - } - - // Don't give me output. - computer.sendInputs("n\n"); - - computer.run(); - - assert(!output_buffer.empty()); - - if (output_buffer.size() == 1) { - output << output_buffer.front() << std::endl; - } else { - std::copy(output_buffer.begin(), output_buffer.end(), std::ostreambuf_iterator(output)); - output << output_buffer.back() << std::endl; - } -} diff --git a/2019/src/day17/route-map.py b/2019/src/day17/route-map.py deleted file mode 100644 index 873b2af..0000000 --- a/2019/src/day17/route-map.py +++ /dev/null @@ -1,76 +0,0 @@ -import fileinput -import sys - - -def turn_left(direction): - x, y = direction - return (y, -x) - - -def turn_right(direction): - x, y = direction - return (-y, x) - - -def add(pos, direction): - return tuple(a + b for a, b in zip(pos, direction)) - - -def main(): - chart = [line.strip() for line in fileinput.input()] - - pos = None - - for y, line in enumerate(chart): - x = line.find('^') - if x >= 0: - pos = (x, y) - break - - if not pos: - sys.exit('starting point not found') - - route = ['L'] - - direction = (-1, 0) - - def bounds_check(pos): - x, y = pos - - return x >= 0 and y >= 0 and y < len(chart) - - while True: - # try to move forward - next_pos = add(direction, pos) - dist = 0 - - while bounds_check(next_pos) and chart[next_pos[1]][next_pos[0]] == '#': - dist += 1 - pos = next_pos - next_pos = add(direction, pos) - - if dist: - route.append(dist) - else: - break - - for move, new_dir in zip(('L', 'R'), (turn_left(direction), turn_right(direction))): - next_pos = add(pos, new_dir) - if bounds_check(next_pos) and chart[next_pos[1]][next_pos[0]] == '#': - route.append(move) - direction = new_dir - break - - printable_route = [] - for x in route: - if x == 'L' or x == 'R': - printable_route.append(x) - else: - printable_route += ['M'] * x - - print(','.join(str(x) for x in route)) - print(','.join(printable_route)) - - -if __name__ == '__main__': - main() diff --git a/2019/src/day18.cpp b/2019/src/day18.cpp deleted file mode 100644 index e5c8452..0000000 --- a/2019/src/day18.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "days.hpp" -#include "point.hpp" - -static_assert(sizeof(int) >= 4, "Int should be at least 32 bits."); - -using namespace std::string_view_literals; - -namespace { - typedef aoc2019::Point point_t; - - typedef std::vector map_t; - - std::array DIRECTIONS = {{ - {0, -1}, - {0, 1}, - {-1, 0}, - {1, 0}, - }}; - - map_t read_map(std::istream &input) { - std::string buffer; - map_t map; - - while (std::getline(input, buffer)) { - map.push_back(buffer); - } - - return map; - } - - point_t find(const std::vector &map, char needle) { - for (int y = 0; y < map.size(); ++y) { - auto x = map[y].find(needle); - if (x != std::string::npos) { - return {(int) x, y}; - } - } - - throw std::invalid_argument("Can't find it!"); - } - - std::vector> find_edges(const map_t &map, point_t starting_point) { - std::vector> edges; - std::queue> todo; - todo.emplace(0, starting_point); - - std::unordered_set visited{starting_point}; - - while (!todo.empty()) { - const auto[dist, pos] = todo.front(); - todo.pop(); - - for (auto &direction : DIRECTIONS) { - auto next_pos = pos + direction; - const char at = map[next_pos[1]][next_pos[0]]; - - if (at == '#' || visited.count(next_pos)) { - // Wall or already visited, ignore - continue; - } - - visited.insert(next_pos); - - if (std::isalpha(at)) { - // Don't walk through stuff - edges.emplace_back(at, dist + 1); - } else { - todo.emplace(dist + 1, next_pos); - } - } - } - - return edges; - } - - auto compute_implied_graph(const map_t &map) { - std::unordered_map>> implied_graph; - - for (int y = 0; y < map.size(); ++y) { - for (int x = 0; x < map[y].size(); ++x) { - char at = map[y][x]; - if ("@/^*"sv.find(at) != std::string_view::npos || std::isalpha(at)) { - implied_graph[at] = find_edges(map, {x, y}); - } - } - } - - return implied_graph; - } - - inline unsigned int key_index(char c) { - return 1u << static_cast(c - 'A'); - } -} - -void aoc2019::day18_part1(std::istream &input, std::ostream &output) { - using state_t = std::tuple; - - const auto map = read_map(input); - - auto implied_graph = compute_implied_graph(map); - - std::priority_queue, std::vector>, std::greater<>> todo; - std::map visited; - todo.emplace(0, std::make_pair(0, '@')); - - auto target_size = std::count_if(implied_graph.cbegin(), implied_graph.cend(), - [](auto &x) { return std::islower(x.first); }); - - while (!todo.empty()) { - const auto[dist, state] = todo.top(); - todo.pop(); - - if (visited[state] < dist) { - continue; - } - - auto[keys, pos] = state; - - if (std::__popcount(keys) == target_size) { - output << dist << std::endl; - return; - } - - for (const auto &edge : implied_graph.at(pos)) { - auto next_dist = dist + edge.second; - auto next_keys = keys; - if (std::islower(edge.first)) { - // Add the key to our collection - next_keys |= key_index(edge.first);; - } else if (std::isupper(edge.first)) { - // Check if we have the required key already - if (!(next_keys & key_index(edge.first))) { - continue; - } - } - - state_t next_state = {next_keys, edge.first}; - if (auto it = visited.find(next_state); it == visited.end() || it->second > next_dist) { - visited[next_state] = next_dist; - todo.emplace(next_dist, next_state); - } - - } - } - - throw std::logic_error("Should have terminated by now."); -} - -void aoc2019::day18_part2(std::istream &input, std::ostream &output) { - using state_t = std::pair>; - - auto map = read_map(input); - - // problem statement says to duplicate @ but where's the fun in that - const auto initial_pos = find(map, '@'); - - // problem statement says to duplicate @ but where's the fun in that, let's have different starting positions - std::array overlay = { - "@#*", - "###", - "^#/", - }; - - for (int y = 0; y < 3; ++y) { - auto &row = map[initial_pos[1] + y - 1]; - std::copy(overlay[y].begin(), overlay[y].end(), row.data() + initial_pos[0] - 1); - } - - const auto implied_graph = compute_implied_graph(map); - - std::priority_queue, std::vector>, std::greater<>> todo; - std::map, int> visited; - todo.emplace(0, state_t(0, {'@', '*', '^', '/'})); - - auto target_size = std::count_if(implied_graph.cbegin(), implied_graph.cend(), - [](auto &x) { return std::islower(x.first); }); - - - while (!todo.empty()) { - const auto[dist, state] = todo.top(); - todo.pop(); - - auto[keys, pos] = state; - - if (std::__popcount(keys) == target_size) { - output << dist << std::endl; - return; - } - - for (int i = 0; i < 4; ++i) { - auto next_pos = pos; - for (const auto &edge : implied_graph.at(pos[i])) { - auto next_dist = dist + edge.second; - auto next_keys = keys; - if (std::islower(edge.first)) { - // Add the key to our collection - next_keys |= key_index(edge.first);; - } else if (std::isupper(edge.first)) { - // Check if we have the required key already - if (!(next_keys & key_index(edge.first))) { - continue; - } - } - - next_pos[i] = edge.first; - - state_t next_state = {next_keys, next_pos}; - if (auto it = visited.find({next_keys, next_pos[i]}); it == visited.end() || it->second > next_dist) { - visited[{next_keys, next_pos[i]}] = next_dist; - todo.emplace(next_dist, next_state); - } - } - } - } - - - output << "Not implemented\n"; -} diff --git a/2019/src/day19.cpp b/2019/src/day19.cpp deleted file mode 100644 index 15eea3c..0000000 --- a/2019/src/day19.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include "days.hpp" -#include "utils.hpp" - -namespace { - bool bounds_check(aoc2019::IntCodeComputer computer, std::int64_t x, std::int64_t y) { - std::deque output_buffer; - computer.connectOutput(output_buffer); - - computer.sendInput(x); - computer.sendInput(y); - - computer.run(); - assert(computer.isTerminated()); - assert(!output_buffer.empty()); - - return output_buffer.front(); - } - - class Beam { - private: - aoc2019::IntCodeComputer computer; - std::int64_t last_width = 1; - std::int64_t last_start = 0; - std::int64_t y = 0; - - public: - Beam(std::istream &input) : computer(input) {}; - - std::pair next() { - auto x = last_start; - - while (!bounds_check(computer, x, y)) { - ++x; - } - - last_start = x; - x += last_width - 1; - - while (bounds_check(computer, x, y)) { - ++x; - } - - last_width = x - last_start; - ++y; - - return {last_start, last_width}; - } - }; -} - -void aoc2019::day19_part1(std::istream &input, std::ostream &output) { - Beam beam(input); - - std::int64_t covered = 0; - for (std::int64_t y = 0; y < 50; ++y) { - const auto[start, width] = beam.next(); - - if (start >= 50) break; - - covered += std::min(50 - start, width); - } - - output << covered << std::endl; -} - -void aoc2019::day19_part2(std::istream &input, std::ostream &output) { - Beam beam(input); - std::queue beam_ends; - - constexpr std::int64_t DIMENSION = 100; - - for (std::int64_t y = 0; true; ++y) { - const auto[start, width] = beam.next(); - - beam_ends.push(start + width); - if (beam_ends.size() == DIMENSION) { - auto end = beam_ends.front(); - if (end - start >= DIMENSION) { - auto result = start * 10000 + y - DIMENSION + 1; - output << result << std::endl; - return; - } - beam_ends.pop(); - } - } -} diff --git a/2019/src/day20.cpp b/2019/src/day20.cpp deleted file mode 100644 index d8087f6..0000000 --- a/2019/src/day20.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "days.hpp" -#include "point.hpp" - -namespace { - typedef aoc2019::Point point_t; - typedef std::vector map_t; - - std::array DIRECTIONS = {{ - {0, -1}, - {0, 1}, - {-1, 0}, - {1, 0}, - }}; - - std::vector read_map(std::istream &input) { - std::string buffer; - std::vector map; - - while (std::getline(input, buffer)) { - map.push_back(buffer); - } - - return map; - } - - auto get_portals(const map_t &map) { - std::unordered_map portals; - - // First find horizontal portals - for (int y = 0; y < map.size(); ++y) { - for (int x = 0; x < map[y].size() - 1; ++x) { - if (std::isalpha(map[y][x]) && std::isalpha(map[y][x + 1])) { - // find out the entry point - point_t entry_point = {0, y}; - if (x > 0 && map[y][x - 1] == '.') { - entry_point[0] = x - 1; - } else { - entry_point[0] = x + 2; - } - - portals[entry_point] = map[y].substr(x, 2); - } - } - } - - char name[3] = {0, 0, 0}; - for (int x = 0; x < map[0].size(); ++x) { - for (int y = 0; y < map.size() - 1; ++y) { - if (std::isalpha(map[y][x]) && std::isalpha(map[y + 1][x])) { - name[0] = map[y][x]; - name[1] = map[y + 1][x]; - - point_t entry_point = {x, 0}; - if (y > 0 && map[y - 1][x] == '.') { - entry_point[1] = y - 1; - } else { - entry_point[1] = y + 2; - } - - portals[entry_point] = name; - } - } - } - - return portals; - } - - std::unordered_map>> - get_implicit_graph(const map_t &map, const std::unordered_map &portals) { - std::unordered_map half_links; - - std::unordered_map>> graph; - - for (auto &entry : portals) { - if (auto it = half_links.find(entry.second); it != half_links.end()) { - // Connect up the portals - graph[it->second].emplace_back(1, entry.first); - graph[entry.first].emplace_back(1, it->second); - } else { - half_links[entry.second] = entry.first; - } - - // Do a BFS from the node to see what we can reach. - std::deque> todo{{0, entry.first}}; - std::unordered_set visited{entry.first}; - - while (!todo.empty()) { - const auto[dist, pos] = todo.front(); - todo.pop_front(); - - for (auto &direction : DIRECTIONS) { - auto next_pos = pos + direction; - - if (map[next_pos[1]][next_pos[0]] != '.' || visited.count(next_pos)) { - continue; - } - - if (portals.count(next_pos)) { - graph[entry.first].emplace_back(dist + 1, next_pos); - } - - todo.emplace_back(dist + 1, next_pos); - visited.insert(next_pos); - } - } - } - - return graph; - } -} - -void aoc2019::day20_part1(std::istream &input, std::ostream &output) { - const auto map = read_map(input); - const auto portals = get_portals(map); - - const auto starting_point = std::find_if(portals.begin(), portals.end(), [](auto &x) { - return x.second == "AA"; - })->first; - - auto graph = get_implicit_graph(map, portals); - - std::unordered_set visited; - std::priority_queue, std::vector>, std::greater<>> todo; - todo.emplace(0, starting_point); - - while (!todo.empty()) { - const auto[dist, pos] = todo.top(); - todo.pop(); - - if (visited.count(pos)) { - continue; - } - - visited.insert(pos); - - if (portals.at(pos) == "ZZ") { - output << dist << std::endl; - return; - } - - for (auto &edge : graph[pos]) { - if (visited.count(edge.second)) { - continue; - } - - todo.emplace(dist + edge.first, edge.second); - } - } - - throw std::domain_error("No valid route."); -} - -void aoc2019::day20_part2(std::istream &input, std::ostream &output) { - const auto map = read_map(input); - const auto portals = get_portals(map); - - using state_t = std::pair; - - const auto starting_point = std::find_if(portals.begin(), portals.end(), [](auto &x) { - return x.second == "AA"; - })->first; - - auto graph = get_implicit_graph(map, portals); - - std::set visited; - std::priority_queue, std::vector>, std::greater<>> todo; - todo.emplace(0, 0, starting_point); - - const int outer_x_min = 2; - const int outer_x_max = map[0].size() - 3; - const int outer_y_min = 2; - const int outer_y_max = map.size() - 3; - - while (!todo.empty()) { - const auto[dist, level, pos] = todo.top(); - todo.pop(); - - if (visited.count({level, pos})) { - continue; - } - - visited.emplace(level, pos); - - if (level == 0 && portals.at(pos) == "ZZ") { - output << dist << std::endl; - return; - } - - for (auto &edge : graph[pos]) { - int mod = 0; - if (edge.first == 1) { - // Taking a portal, determine which level we're going to - if (pos[0] == outer_x_max || pos[0] == outer_x_min || pos[1] == outer_y_max || pos[1] == outer_y_min) { - mod = -1; - } else { - mod = 1; - } - } - - if (level + mod < 0 || visited.count({level + mod, edge.second})) { - continue; - } - - todo.emplace(dist + edge.first, level + mod, edge.second); - } - } - - throw std::domain_error("No valid route."); -} diff --git a/2019/src/day21.cpp b/2019/src/day21.cpp deleted file mode 100644 index d231041..0000000 --- a/2019/src/day21.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "days.hpp" -#include "utils.hpp" - -namespace { - void solve(std::istream &input, std::string_view program, std::ostream &output) { - aoc2019::IntCodeComputer computer(input); - std::deque output_buffer; - computer.connectOutput(output_buffer); - computer.run(); - output_buffer.clear(); - - computer.sendInputs(program); - - computer.run(); - if (output_buffer.back() < 127) { - for (char c : output_buffer) { - output << c; - } - } else { - output << output_buffer.back() << std::endl; - } - } -} - -void aoc2019::day21_part1(std::istream &input, std::ostream &output) { - std::string_view program = "OR A J\n" // Check if any of the next 3 places is a hole - "AND B J\n" - "AND C J\n" - "NOT J J\n" - "AND D J\n" // Jump if the landing space is clear - "WALK\n"; - - solve(input, program, output); -} - -void aoc2019::day21_part2(std::istream &input, std::ostream &output) { - std::string_view program = "NOT H J\n" // If you can safely jump twice - "OR C J\n" // And either of the next 3 places contains a hole - "AND A J\n" - "AND B J\n" - "NOT J J\n" - "AND D J\n" // And we can land our first jump, then jump. - "RUN\n"; - - solve(input, program, output); -} diff --git a/2019/src/day22.cpp b/2019/src/day22.cpp deleted file mode 100644 index 3900157..0000000 --- a/2019/src/day22.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include "days.hpp" -#include "utils.hpp" - -namespace { - enum class Operation { - Stack, - Deal, - Cut - }; - - using Move = std::pair; - - std::vector read_moves(std::istream &input) { - std::string buffer; - std::vector moves; - - while (std::getline(input, buffer)) { - std::string_view line = buffer; - if (!line.find("deal into new stack")) { - moves.emplace_back(Operation::Stack, 0); - } else if (!line.find("deal with increment ")) { - int new_increment; - aoc2019::from_chars(line.substr(20), new_increment); - moves.emplace_back(Operation::Deal, new_increment); - } else { - // cut - int new_offset; - aoc2019::from_chars(line.substr(4), new_offset); - - moves.emplace_back(Operation::Cut, new_offset); - } - } - - return moves; - } - - constexpr std::int64_t mmi(std::int64_t a, std::int64_t n) { - std::int64_t t = 0, newt = 1, r = n, newr = a; - - while (newr != 0) { - auto q = r / newr; - // Poor man's simultaneous assignment - std::tie(t, newt) = std::make_tuple(newt, t - q * newt); - std::tie(r, newr) = std::make_tuple(newr, r - q * newr); - } - - if (r > 1) { - throw std::invalid_argument("Not invertible."); - } - - if (t < 0) t += n; - - assert((t * a) % n == 1); - - return t; - } - - constexpr std::pair pow(std::int64_t a, std::int64_t b, std::int64_t n, const std::int64_t M) { - __int128 ra = 0, rb = 0; - - while (n > 0) { - if (n % 2) { - ra = (ra + a) % M; - rb = (rb + b) % M; - } - - // f(x) = ax + b - // f(f(x)) = a(ax + b) + b - // = aax + ab + b - __int128 na = a * (__int128) a; - __int128 nb = b * (__int128) a + b; - - a = na % M; - b = nb % M; - - n /= 2; - } - - return {ra, rb}; - } -} - -void aoc2019::day22_part1(std::istream &input, std::ostream &output) { - constexpr int DECK_SIZE = 10007; - - int pos = 2019; - - for (auto move : read_moves(input)) { - int argument = move.second; - switch (move.first) { - case Operation::Stack: - pos = DECK_SIZE - 1 - pos; - break; - - case Operation::Deal: - pos = pos * argument % DECK_SIZE; - break; - - case Operation::Cut: - pos = (pos - argument) % DECK_SIZE; - if (pos < 0) pos += DECK_SIZE; - break; - } - } - - output << pos << std::endl; -} - -void aoc2019::day22_part2(std::istream &input, std::ostream &output) { - constexpr std::int64_t DECK_SIZE = 119315717514047; - constexpr std::int64_t SHUFFLES = 101741582076661; - - assert(mmi(3, 11) == 4); - - std::int64_t a = 1, b = 0; - - for (auto move : read_moves(input)) { - std::int64_t argument = move.second; - switch (move.first) { - case Operation::Stack: - a = -a; - b = DECK_SIZE - b - 1; - break; - - case Operation::Cut: - b = (b + argument) % DECK_SIZE; - break; - - case Operation::Deal: - __int128 inv = mmi(argument, DECK_SIZE); - a = (a * inv) % DECK_SIZE; - b = (b * inv) % DECK_SIZE; - break; - } - } - - const auto[ra, rb] = pow(a, b, SHUFFLES, DECK_SIZE); - - output << ra << ',' << rb << std::endl; - - auto result = (2020 * ra + rb) % DECK_SIZE; - if (result < 0) { - result += DECK_SIZE; - } - - output << result << std::endl; -} diff --git a/2019/src/day23.cpp b/2019/src/day23.cpp deleted file mode 100644 index 383e9f5..0000000 --- a/2019/src/day23.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include "days.hpp" - -void aoc2019::day23_part1(std::istream &input, std::ostream &output) { - output << "Not implemented\n"; -} - -void aoc2019::day23_part2(std::istream &input, std::ostream &output) { - output << "Not implemented\n"; -} diff --git a/2019/src/day24.cpp b/2019/src/day24.cpp deleted file mode 100644 index 3d69eea..0000000 --- a/2019/src/day24.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include -#include -#include -#include "days.hpp" - -namespace { - using field_t = std::array, 5>; - - constexpr int EDGE = 4; - constexpr int MIDPOINT = 2; - - field_t read_input(std::istream &input) { - std::string buffer; - field_t map; - - int y = 0; - - while (std::getline(input, buffer)) { - auto &row = map[y++]; - - std::transform(buffer.begin(), buffer.end(), row.begin(), [](char c) { return c == '#'; }); - } - - return map; - } - - void next_gen(const field_t &source, field_t &sink) { - for (int y = 0; y < source.size(); ++y) { - for (int x = 0; x < source[y].size(); ++x) { - int neighbours = source[y][x] ? -1 : 0; - for (int dy = -1; dy <= 1; ++dy) { - if (dy + y < 0 || dy + y >= source.size()) { - continue; - } - for (int dx = -1; dx <= 1; ++dx) { - if (dx + x < 0 || dx + x >= source[y].size() || dx * dy) { - continue; - } - neighbours += source[y + dy][x + dx]; - } - } - - sink[y][x] = neighbours == 1 || (!source[y][x] && neighbours == 2); - } - } - } - - int num_bees(const field_t &field) { - int total = 0; - for (auto &row : field) { - total += std::count(row.begin(), row.end(), true); - } - - return total; - } - - std::unordered_map advance(const std::unordered_map &state) { - const auto dimension_range = std::minmax_element(state.begin(), state.end()); - const auto min = dimension_range.first->first - 1; - const auto max = dimension_range.second->first + 1; - - std::unordered_map next_gen; - - auto has_bee = [&state](int dimension, int x, int y) { - if (auto it = state.find(dimension); it != state.end()) { - return it->second[y][x]; - } - - return false; - }; - - for (int dimension = min; dimension <= max; ++dimension) { - field_t field{}; - if (auto it = state.find(dimension); it != state.end()) { - field = it->second; - } - - auto get_neighbours = [has_bee,dimension](int x, int y) { - int neighbours = 0; - - // Cell above - if (y == 0) { - neighbours += has_bee(dimension + 1, MIDPOINT, 1); - } else if (y == 3 && x == MIDPOINT) { - for (int sx = 0; sx < 5; ++sx) { - neighbours += has_bee(dimension - 1, sx, EDGE); - } - } else { - neighbours += has_bee(dimension, x, y - 1); - } - - // Cell below - if (y == EDGE) { - neighbours += has_bee(dimension + 1, MIDPOINT, 3); - } else if (y == 1 && x == MIDPOINT) { - for (int sx = 0; sx < 5; ++sx) { - neighbours += has_bee(dimension - 1, sx, 0); - } - } else { - neighbours += has_bee(dimension, x, y + 1); - } - - // Cell left - if (x == 0) { - neighbours += has_bee(dimension + 1, 1, 2); - } else if (x == 3 && y == MIDPOINT) { - for (int sy = 0; sy < 5; ++sy) { - neighbours += has_bee(dimension - 1, EDGE, sy); - } - } else { - neighbours += has_bee(dimension, x - 1, y); - } - - // Cell right - if (x == EDGE) { - neighbours += has_bee(dimension + 1, 3, MIDPOINT); - } else if (x == 1 && y == MIDPOINT) { - for (int sy = 0; sy < 5; ++sy) { - neighbours += has_bee(dimension - 1, 0, sy); - } - } else { - neighbours += has_bee(dimension, x + 1, y); - } - - return neighbours; - }; - - - for (int y = 0; y < 5; ++y) { - for (int x = 0; x < 5; ++x) { - auto neighbours = get_neighbours(x, y); - field[y][x] = neighbours == 1 || (neighbours == 2 && !field[y][x]); - } - } - - // Don't evolve the midpoint. - field[2][2] = false; - - if (num_bees(field) || (dimension != min && dimension != max)) { - next_gen[dimension] = field; - } - } - - return next_gen; - } -} - -void aoc2019::day24_part1(std::istream &input, std::ostream &output) { - auto map = read_input(input); - auto copy = map; - - std::set seen; - do { - seen.insert(map); - next_gen(map, copy); - std::swap(map, copy); - } while (!seen.count(map)); - - unsigned int pow = 1; - unsigned int diversity = 0; - for (auto &row : map) { - for (auto b : row) { - if (b) { - diversity += pow; - } - - pow <<= 1u; - } - } - output << diversity << std::endl; -} - -void aoc2019::day24_part2(std::istream &input, std::ostream &output) { - std::unordered_map fields; - fields[0] = read_input(input); - - for (int gen = 0; gen < 200; ++gen) { - fields = advance(fields); - } - - int total = std::accumulate(fields.begin(), fields.end(), 0, [](auto cur, const auto &it) { - return cur + num_bees(it.second); - }); - - output << total << std::endl; -} diff --git a/2019/src/day25.cpp b/2019/src/day25.cpp deleted file mode 100644 index 0eb6ade..0000000 --- a/2019/src/day25.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include "days.hpp" - -void aoc2019::day25_part1(std::istream &input, std::ostream &output) { - output << "Not implemented\n"; -} - -void aoc2019::day25_part2(std::istream &input, std::ostream &output) { - output << "Not implemented\n"; -} diff --git a/2019/src/days.hpp b/2019/src/days.hpp deleted file mode 100644 index f34ed64..0000000 --- a/2019/src/days.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include - -namespace aoc2019 { - // Declarations of all implemented days. - void day01_part1(std::istream &input, std::ostream &output); - void day01_part2(std::istream &input, std::ostream &output); - void day02_part1(std::istream &input, std::ostream &output); - void day02_part2(std::istream &input, std::ostream &output); - void day03_part1(std::istream &input, std::ostream &output); - void day03_part2(std::istream &input, std::ostream &output); - void day04_part1(std::istream &input, std::ostream &output); - void day04_part2(std::istream &input, std::ostream &output); - void day05_part1(std::istream &input, std::ostream &output); - void day05_part2(std::istream &input, std::ostream &output); - void day06_part1(std::istream &input, std::ostream &output); - void day06_part2(std::istream &input, std::ostream &output); - void day07_part1(std::istream &input, std::ostream &output); - void day07_part2(std::istream &input, std::ostream &output); - void day08_part1(std::istream &input, std::ostream &output); - void day08_part2(std::istream &input, std::ostream &output); - void day09_part1(std::istream &input, std::ostream &output); - void day09_part2(std::istream &input, std::ostream &output); - void day10_part1(std::istream &input, std::ostream &output); - void day10_part2(std::istream &input, std::ostream &output); - void day11_part1(std::istream &input, std::ostream &output); - void day11_part2(std::istream &input, std::ostream &output); - void day12_part1(std::istream &input, std::ostream &output); - void day12_part2(std::istream &input, std::ostream &output); - void day13_part1(std::istream &input, std::ostream &output); - void day13_part2(std::istream &input, std::ostream &output); - void day14_part1(std::istream &input, std::ostream &output); - void day14_part2(std::istream &input, std::ostream &output); - void day15_part1(std::istream &input, std::ostream &output); - void day15_part2(std::istream &input, std::ostream &output); - void day16_part1(std::istream &input, std::ostream &output); - void day16_part2(std::istream &input, std::ostream &output); - void day17_part1(std::istream &input, std::ostream &output); - void day17_part2(std::istream &input, std::ostream &output); - void day18_part1(std::istream &input, std::ostream &output); - void day18_part2(std::istream &input, std::ostream &output); - void day19_part1(std::istream &input, std::ostream &output); - void day19_part2(std::istream &input, std::ostream &output); - void day20_part1(std::istream &input, std::ostream &output); - void day20_part2(std::istream &input, std::ostream &output); - void day21_part1(std::istream &input, std::ostream &output); - void day21_part2(std::istream &input, std::ostream &output); - void day22_part1(std::istream &input, std::ostream &output); - void day22_part2(std::istream &input, std::ostream &output); - void day23_part1(std::istream &input, std::ostream &output); - void day23_part2(std::istream &input, std::ostream &output); - void day24_part1(std::istream &input, std::ostream &output); - void day24_part2(std::istream &input, std::ostream &output); - void day25_part1(std::istream &input, std::ostream &output); - void day25_part2(std::istream &input, std::ostream &output); -} diff --git a/2019/src/implementations.cpp b/2019/src/implementations.cpp deleted file mode 100644 index 9111331..0000000 --- a/2019/src/implementations.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "days.hpp" -#include "implementations.hpp" - -constexpr const std::array, 25> SOLUTIONS = {{ - {aoc2019::day01_part1, aoc2019::day01_part2}, - {aoc2019::day02_part1, aoc2019::day02_part2}, - {aoc2019::day03_part1, aoc2019::day03_part2}, - {aoc2019::day04_part1, aoc2019::day04_part2}, - {aoc2019::day05_part1, aoc2019::day05_part2}, - {aoc2019::day06_part1, aoc2019::day06_part2}, - {aoc2019::day07_part1, aoc2019::day07_part2}, - {aoc2019::day08_part1, aoc2019::day08_part2}, - {aoc2019::day09_part1, aoc2019::day09_part2}, - {aoc2019::day10_part1, aoc2019::day10_part2}, - {aoc2019::day11_part1, aoc2019::day11_part2}, - {aoc2019::day12_part1, aoc2019::day12_part2}, - {aoc2019::day13_part1, aoc2019::day13_part2}, - {aoc2019::day14_part1, aoc2019::day14_part2}, - {aoc2019::day15_part1, aoc2019::day15_part2}, - {aoc2019::day16_part1, aoc2019::day16_part2}, - {aoc2019::day17_part1, aoc2019::day17_part2}, - {aoc2019::day18_part1, aoc2019::day18_part2}, - {aoc2019::day19_part1, aoc2019::day19_part2}, - {aoc2019::day20_part1, aoc2019::day20_part2}, - {aoc2019::day21_part1, aoc2019::day21_part2}, - {aoc2019::day22_part1, aoc2019::day22_part2}, - {aoc2019::day23_part1, aoc2019::day23_part2}, - {aoc2019::day24_part1, aoc2019::day24_part2}, - {aoc2019::day25_part1, aoc2019::day25_part2}, -}}; - -aoc2019::solution_t aoc2019::get_implementation(int day, bool part2) { - return SOLUTIONS.at(day - 1).at((int) part2); -} diff --git a/2019/src/implementations.hpp b/2019/src/implementations.hpp deleted file mode 100644 index 24e9820..0000000 --- a/2019/src/implementations.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -namespace aoc2019 { - typedef void (*solution_t)(std::istream &, std::ostream &); - - solution_t get_implementation(int day, bool part2 = false); -} diff --git a/2019/src/point.hpp b/2019/src/point.hpp deleted file mode 100644 index d123475..0000000 --- a/2019/src/point.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include -#include -#include "utils.hpp" - -namespace aoc2019 { - template - class Point : public std::array { - public: - constexpr Point& operator +=(Point other) { - for (std::size_t i = 0; i < L; ++i) { - (*this)[i] += other[i]; - } - return *this; - } - - constexpr Point operator+(Point other) const { - auto result = *this; - result += other; - - return result; - } - - constexpr Point& operator -=(Point other) { - for (std::size_t i = 0; i < L; ++i) { - (*this)[i] -= other[i]; - } - - return *this; - } - - constexpr Point operator-(Point other) const { - auto result = *this; - result -= other; - - return result; - } - - constexpr T l1() const { - T result = 0; - for (auto e : *this) { - result += std::abs(e); - } - - return result; - } - }; - - template - std::pair, Point> bounding_box(const std::unordered_map, Ignored> &data) { - Point lower, upper; - std::fill(lower.begin(), lower.end(), std::numeric_limits::max()); - std::fill(upper.begin(), upper.end(), std::numeric_limits::min()); - - for (auto &entry : data) { - for (int i = 0; i < N; ++i) { - lower[i] = std::min(entry.first[i], lower[i]); - upper[i] = std::max(entry.first[i], upper[i]); - } - } - - return {lower, upper}; - } -} - -namespace std { - // Make point usable with unordered collections. - template struct hash> { - size_t operator()(const aoc2019::Point &o) const { - size_t seed = 0; - for (auto i : o) { - aoc2019::combine_hash(seed, i); - } - return seed; - } - }; -} diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp deleted file mode 100644 index a640346..0000000 --- a/2019/src/runner.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "implementations.hpp" -#include -#include -#include -#include -#include -#include - -struct AoCOptions { - aoc2019::solution_t implementation; - bool run_timer; - std::optional input_file; -}; - -static AoCOptions parse_options(const int argc, const char* argv[]) { - using namespace std::literals; - AoCOptions options{}; - - auto show_help = [argv] (int exit_status = 0) { - std::cerr << "Usage: " << argv[0] << " [--timer|-t] [--part2|-2] [--help|-h] DAY\n" - << "\t--timer|-t: print execution time\n" - << "\t--input ARG|-fARG: use given input file as puzzle input" - << "\t--part2|-2: run part 2\n" - << "\t --help|-h: show this message\n"; - std::exit(exit_status); - }; - - int day = -1; - bool part2 = false; - - // Here follows a manual implementation of getopt, since getopt doesn't work on windows… - for (int i = 1; i < argc; ++i) { - std::string_view arg(argv[i]); - if (arg[0] == '-') { - // Handle flag arguments - if (arg[1] != '-') { - // Shorthand flags - for (int j = 1; j < arg.size(); ++j) { - switch (arg[j]) { - case '2': - part2 = true; - break; - - case 't': - options.run_timer = true; - break; - - case 'h': - show_help(); - break; - - case 'f': - if (j == arg.size() - 1) { - if (i == argc - 1) { - std::cerr << "Option -f requires an argument."; - show_help(1); - } else { - options.input_file = std::ifstream(argv[i + 1]); - ++i; - } - } else { - options.input_file = std::ifstream(std::string(arg.substr(j))); - j = arg.size(); - } - break; - - default: - std::cerr << "Unknown flag '" << arg[j] << "'.\n\n"; - show_help(1); - } - } - } else { - // Handle long form versions - if (arg == "--timer"sv) { - part2 = true; - } else if (arg == "--timer"sv) { - options.run_timer = true; - } else if (arg == "--help"sv) { - show_help(); - } else if (arg == "--input"sv) { - if (i == argc - 1) { - std::cerr << "Option -f requires an argument."; - show_help(1); - } else { - options.input_file = std::ifstream(argv[i + 1]); - ++i; - } - } else { - show_help(1); - } - } - } else { - if (day != -1) { - // Double date specification, bail. - show_help(1); - } - - // Try to parse the date number - if (auto res = std::from_chars(arg.data(), arg.data() + arg.size(), day); res.ec != std::errc()) { - auto error_code = std::make_error_code(res.ec); - std::cerr << error_code.message() << "\n\n"; - show_help(1); - } - } - } - - if (day == -1) { - std::cerr << "Argument DAY is required.\n\n"; - show_help(1); - } else if (day < 1 || day > 25) { - std::cerr << "Invalid day. Valid range: [1, 25]\n"; - show_help(1); - } - - options.implementation = aoc2019::get_implementation(day, part2); - - return options; -} - -int main(int argc, const char *argv[]) { - auto options = parse_options(argc, argv); - - if (options.implementation != nullptr) { - const auto start = std::chrono::high_resolution_clock::now(); - options.implementation(options.input_file ? *options.input_file : std::cin, std::cout); - if (options.run_timer) { - const std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; - std::cerr << "Time taken: " << duration.count() << "s\n"; - } - return 0; - } else { - std::cerr << "Unimplemented.\n"; - return 1; - } -} diff --git a/2019/src/utils.cpp b/2019/src/utils.cpp deleted file mode 100644 index a037303..0000000 --- a/2019/src/utils.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include "utils.hpp" - -std::string_view aoc2019::strtok(std::string_view &str, char token) { - auto next_delim = str.find(token); - auto next = str.substr(0, next_delim); - if (next_delim == std::string_view::npos) { - str = {}; - } else { - str = str.substr(next_delim + 1); - } - return next; -} - -std::deque aoc2019::run_intcode(std::vector program, std::deque inputs) { - std::deque outputs; - IntCodeComputer computer(std::move(program), std::move(inputs)); - computer.connectOutput(outputs); - - computer.run(); - - return outputs; -} - -aoc2019::IntCodeComputer::value_t &aoc2019::IntCodeComputer::interpret_value(int pos) { - value_t immediate; - switch (pos) { - case 1: - immediate = program[ip] / 100 % 10; - break; - case 2: - immediate = program[ip] / 1000 % 10; - break; - - case 3: - immediate = program[ip] / 10000 % 10; - break; - - default: - throw std::out_of_range("Invalid position"); - } - - value_t index; - - switch (immediate) { - case 0: - index = program[ip + pos]; - break; - - case 1: - index = ip + pos; - break; - - case 2: - index = program[ip + pos] + relative; - break; - - default: - throw std::out_of_range("Invalid mode"); - } - - if (program.size() <= index) { - program.resize(index + 1); - } - - return program[index]; -} - -void aoc2019::IntCodeComputer::connectOutput(aoc2019::IntCodeComputer &computer) { - outputSink = &computer.inputs; -} - -void aoc2019::IntCodeComputer::connectOutput(std::deque &sink) { - outputSink = &sink; -} - -bool aoc2019::IntCodeComputer::isTerminated() const { - return halted; -} - -const std::deque &aoc2019::IntCodeComputer::currentInputs() const { - return inputs; -} - -std::vector aoc2019::IntCodeComputer::read_intcode(std::istream &input) { - std::vector program; - for (value_t current; input >> current; input.ignore()) { - program.push_back(current); - } - - return program; -} - -void aoc2019::IntCodeComputer::run() { - while (ip < program.size()) { - switch (program[ip] % 100) { - case 1: - interpret_value(3) = interpret_value(1) + interpret_value(2); - ip += 4; - break; - - case 2: - interpret_value(3) = interpret_value(1) * interpret_value(2); - ip += 4; - break; - - case 3: - if (inputs.empty()) { - return; - } - - interpret_value(1) = inputs.front(); - inputs.pop_front(); - ip += 2; - break; - - case 4: - outputSink->push_back(interpret_value(1)); - ip += 2; - break; - - case 5: // Jump if non-zero - if (interpret_value(1)) { - ip = interpret_value(2); - } else { - ip += 3; - } - break; - - case 6: // Jump if zero - if (!interpret_value(1)) { - ip = interpret_value(2); - } else { - ip += 3; - } - break; - - case 7: // less than - interpret_value(3) = interpret_value(1) < interpret_value(2); - ip += 4; - break; - - case 8: // equality - interpret_value(3) = interpret_value(1) == interpret_value(2) ? 1 : 0; - ip += 4; - break; - - case 9: - relative += interpret_value(1); - ip += 2; - break; - - case 99: - halted = true; - return; - - default: - char buffer[30]; - std::snprintf(buffer, sizeof(buffer), "Invalid opcode: %d", program[ip]); - - throw std::domain_error(buffer); - } - } -} - -aoc2019::IntCodeComputer::IntCodeComputer(std::vector program, std::deque initial_inputs) : - program{std::move(program)}, inputs{std::move(initial_inputs)} { -} - - -aoc2019::IntCodeComputer::IntCodeComputer(std::istream &program_stream, std::deque initial_inputs) : - program(read_intcode(program_stream)), inputs(std::move(initial_inputs)) { -} - -void aoc2019::IntCodeComputer::sendInput(aoc2019::IntCodeComputer::value_t input) { - inputs.push_back(input); -} - -aoc2019::IntCodeComputer::value_t &aoc2019::IntCodeComputer::operator[](std::size_t index) { - return program[index]; -} - -const aoc2019::IntCodeComputer::value_t &aoc2019::IntCodeComputer::operator[](std::size_t index) const { - return program[index]; -} - -void aoc2019::IntCodeComputer::sendInputs(std::string_view str) { - for (char c : str) { - sendInput(c); - } -} diff --git a/2019/src/utils.hpp b/2019/src/utils.hpp deleted file mode 100644 index c339813..0000000 --- a/2019/src/utils.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace aoc2019 { - - template - inline std::from_chars_result from_chars(std::string_view str, T &value) { - return std::from_chars(str.data(), str.data() + str.size(), value); - } - - template - void combine_hash(std::size_t &seed, const T &o) { - // Algorithm taken from boost::combine_hash. - std::hash hash{}; - seed ^= hash(o) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - } - - template - std::istream &read_line_numbers_and_garbage(std::istream &input, OutputIt output) { - ValueType v; - char c; - while (input && (c = input.peek()) != '\n') { - if (c == '-' || std::isdigit(c)) { - input >> v; - *output = v; - ++output; - } else { - input.ignore(); - } - } - - input.get(); - - return input; - } - - std::string_view strtok(std::string_view &str, char token = ','); - - std::deque run_intcode(std::vector program, std::deque inputs = {}); - - template - std::vector topological_sort(const std::unordered_map> &edge_list) { - std::unordered_map incoming_edges; - - for (auto &entry : edge_list) { - // Ensure entry for parent exist - incoming_edges[entry.first] += 0; - - for (auto &node : entry.second) { - incoming_edges[node]++; - } - } - - std::vector order; - std::deque childless; - - for (auto &entry : incoming_edges) { - if (!entry.second) { - childless.push_back(entry.first); - } - } - - while (!childless.empty()) { - auto current = childless.front(); - childless.pop_front(); - order.emplace_back(current); - - if (auto it = edge_list.find(current); it != edge_list.end()) { - for (const auto &parent : it->second) { - if (--incoming_edges[parent] == 0) { - childless.push_back(parent); - } - } - } - } - - if (order.size() != incoming_edges.size()) { - throw std::domain_error("Not a DAG."); - } - - return order; - } - - class IntCodeComputer { - public: - typedef std::int64_t value_t; - - explicit IntCodeComputer(std::vector program, std::deque initial_inputs = {}); - explicit IntCodeComputer(std::istream &program_stream, std::deque initial_inputs = {}); - - void run(); - void connectOutput(IntCodeComputer &computer); - void connectOutput(std::deque &sink); - void sendInput(value_t input); - - void sendInputs(std::string_view str); - - [[nodiscard]] bool isTerminated() const; - - [[nodiscard]] const std::deque ¤tInputs() const; - - value_t &operator[](std::size_t index); - const value_t &operator[](std::size_t index) const; - - static std::vector read_intcode(std::istream &input); - - private: - std::vector program; - std::deque inputs = {}; - std::deque *outputSink = nullptr; - int ip = 0; - int relative = 0; - bool halted = false; - - [[nodiscard]] value_t &interpret_value(int pos); - }; -} diff --git a/2019/tests/samples/.gitkeep b/2019/tests/samples/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/2019/tests/samples/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/2019/tests/samples/01-1-1.in b/2019/tests/samples/01-1-1.in deleted file mode 100644 index ff999fc..0000000 --- a/2019/tests/samples/01-1-1.in +++ /dev/null @@ -1 +0,0 @@ -100756 diff --git a/2019/tests/samples/01-1-1.out b/2019/tests/samples/01-1-1.out deleted file mode 100644 index 4407060..0000000 --- a/2019/tests/samples/01-1-1.out +++ /dev/null @@ -1 +0,0 @@ -33583 diff --git a/2019/tests/samples/03-1-1.in b/2019/tests/samples/03-1-1.in deleted file mode 100644 index 620a05e..0000000 --- a/2019/tests/samples/03-1-1.in +++ /dev/null @@ -1,2 +0,0 @@ -R75,D30,R83,U83,L12,D49,R71,U7,L72 -U62,R66,U55,R34,D71,R55,D58,R83 diff --git a/2019/tests/samples/03-1-1.out b/2019/tests/samples/03-1-1.out deleted file mode 100644 index 3f7d191..0000000 --- a/2019/tests/samples/03-1-1.out +++ /dev/null @@ -1 +0,0 @@ -159 diff --git a/2019/tests/samples/03-1-2.in b/2019/tests/samples/03-1-2.in deleted file mode 100644 index 4f3a2a4..0000000 --- a/2019/tests/samples/03-1-2.in +++ /dev/null @@ -1,2 +0,0 @@ -R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51 -U98,R91,D20,R16,D67,R40,U7,R15,U6,R7 diff --git a/2019/tests/samples/03-1-2.out b/2019/tests/samples/03-1-2.out deleted file mode 100644 index c8b255f..0000000 --- a/2019/tests/samples/03-1-2.out +++ /dev/null @@ -1 +0,0 @@ -135 diff --git a/2019/tests/samples/03-1-3.in b/2019/tests/samples/03-1-3.in deleted file mode 100644 index 73b95a1..0000000 --- a/2019/tests/samples/03-1-3.in +++ /dev/null @@ -1,2 +0,0 @@ -R8,U5,L5,D3 -U7,R6,D4,L4 diff --git a/2019/tests/samples/03-1-3.out b/2019/tests/samples/03-1-3.out deleted file mode 100644 index 1e8b314..0000000 --- a/2019/tests/samples/03-1-3.out +++ /dev/null @@ -1 +0,0 @@ -6 diff --git a/2019/tests/samples/03-2-1.in b/2019/tests/samples/03-2-1.in deleted file mode 120000 index 0a78c00..0000000 --- a/2019/tests/samples/03-2-1.in +++ /dev/null @@ -1 +0,0 @@ -03-1-1.in \ No newline at end of file diff --git a/2019/tests/samples/03-2-1.out b/2019/tests/samples/03-2-1.out deleted file mode 100644 index 502380c..0000000 --- a/2019/tests/samples/03-2-1.out +++ /dev/null @@ -1 +0,0 @@ -610 diff --git a/2019/tests/samples/03-2-2.in b/2019/tests/samples/03-2-2.in deleted file mode 120000 index 7594846..0000000 --- a/2019/tests/samples/03-2-2.in +++ /dev/null @@ -1 +0,0 @@ -03-1-2.in \ No newline at end of file diff --git a/2019/tests/samples/03-2-2.out b/2019/tests/samples/03-2-2.out deleted file mode 100644 index 17e344e..0000000 --- a/2019/tests/samples/03-2-2.out +++ /dev/null @@ -1 +0,0 @@ -410 diff --git a/2019/tests/samples/03-2-3.in b/2019/tests/samples/03-2-3.in deleted file mode 120000 index 73744a7..0000000 --- a/2019/tests/samples/03-2-3.in +++ /dev/null @@ -1 +0,0 @@ -03-1-3.in \ No newline at end of file diff --git a/2019/tests/samples/03-2-3.out b/2019/tests/samples/03-2-3.out deleted file mode 100644 index 64bb6b7..0000000 --- a/2019/tests/samples/03-2-3.out +++ /dev/null @@ -1 +0,0 @@ -30 diff --git a/2019/tests/samples/06-1-1.in b/2019/tests/samples/06-1-1.in deleted file mode 100644 index 183242d..0000000 --- a/2019/tests/samples/06-1-1.in +++ /dev/null @@ -1,11 +0,0 @@ -COM)B -B)C -C)D -D)E -E)F -B)G -G)H -D)I -E)J -J)K -K)L diff --git a/2019/tests/samples/06-1-1.out b/2019/tests/samples/06-1-1.out deleted file mode 100644 index d81cc07..0000000 --- a/2019/tests/samples/06-1-1.out +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/2019/tests/samples/06-2-1.in b/2019/tests/samples/06-2-1.in deleted file mode 100644 index a1007c6..0000000 --- a/2019/tests/samples/06-2-1.in +++ /dev/null @@ -1,13 +0,0 @@ -COM)B -B)C -C)D -D)E -E)F -B)G -G)H -D)I -E)J -J)K -K)L -K)YOU -I)SAN diff --git a/2019/tests/samples/06-2-1.out b/2019/tests/samples/06-2-1.out deleted file mode 100644 index b8626c4..0000000 --- a/2019/tests/samples/06-2-1.out +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/2019/tests/samples/07-1-1.in b/2019/tests/samples/07-1-1.in deleted file mode 100644 index e626457..0000000 --- a/2019/tests/samples/07-1-1.in +++ /dev/null @@ -1 +0,0 @@ -3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0 diff --git a/2019/tests/samples/07-1-1.out b/2019/tests/samples/07-1-1.out deleted file mode 100644 index d977160..0000000 --- a/2019/tests/samples/07-1-1.out +++ /dev/null @@ -1 +0,0 @@ -43210 diff --git a/2019/tests/samples/07-1-2.in b/2019/tests/samples/07-1-2.in deleted file mode 100644 index 99ab27e..0000000 --- a/2019/tests/samples/07-1-2.in +++ /dev/null @@ -1,2 +0,0 @@ -3,23,3,24,1002,24,10,24,1002,23,-1,23, -101,5,23,23,1,24,23,23,4,23,99,0,0 diff --git a/2019/tests/samples/07-1-2.out b/2019/tests/samples/07-1-2.out deleted file mode 100644 index 67c0579..0000000 --- a/2019/tests/samples/07-1-2.out +++ /dev/null @@ -1 +0,0 @@ -54321 diff --git a/2019/tests/samples/07-1-3.in b/2019/tests/samples/07-1-3.in deleted file mode 100644 index 6f8a3b2..0000000 --- a/2019/tests/samples/07-1-3.in +++ /dev/null @@ -1,2 +0,0 @@ -3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33, -1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0 diff --git a/2019/tests/samples/07-1-3.out b/2019/tests/samples/07-1-3.out deleted file mode 100644 index 8c1ca06..0000000 --- a/2019/tests/samples/07-1-3.out +++ /dev/null @@ -1 +0,0 @@ -65210 diff --git a/2019/tests/samples/07-2-1.in b/2019/tests/samples/07-2-1.in deleted file mode 100644 index 3778360..0000000 --- a/2019/tests/samples/07-2-1.in +++ /dev/null @@ -1,2 +0,0 @@ -3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26, -27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5 diff --git a/2019/tests/samples/07-2-1.out b/2019/tests/samples/07-2-1.out deleted file mode 100644 index 76bf43f..0000000 --- a/2019/tests/samples/07-2-1.out +++ /dev/null @@ -1 +0,0 @@ -139629729 diff --git a/2019/tests/samples/07-2-2.in b/2019/tests/samples/07-2-2.in deleted file mode 100644 index 6aa329f..0000000 --- a/2019/tests/samples/07-2-2.in +++ /dev/null @@ -1,3 +0,0 @@ -3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54, --5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4, -53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10 diff --git a/2019/tests/samples/07-2-2.out b/2019/tests/samples/07-2-2.out deleted file mode 100644 index 1c14ce2..0000000 --- a/2019/tests/samples/07-2-2.out +++ /dev/null @@ -1 +0,0 @@ -18216 diff --git a/2019/tests/samples/10-1-1.in b/2019/tests/samples/10-1-1.in deleted file mode 100644 index 737ae7f..0000000 --- a/2019/tests/samples/10-1-1.in +++ /dev/null @@ -1,5 +0,0 @@ -.#..# -..... -##### -....# -...## diff --git a/2019/tests/samples/10-1-1.out b/2019/tests/samples/10-1-1.out deleted file mode 100644 index 45a4fb7..0000000 --- a/2019/tests/samples/10-1-1.out +++ /dev/null @@ -1 +0,0 @@ -8 diff --git a/2019/tests/samples/10-1-2.in b/2019/tests/samples/10-1-2.in deleted file mode 100644 index 987698f..0000000 --- a/2019/tests/samples/10-1-2.in +++ /dev/null @@ -1,10 +0,0 @@ -......#.#. -#..#.#.... -..#######. -.#.#.###.. -.#..#..... -..#....#.# -#..#....#. -.##.#..### -##...#..#. -.#....#### diff --git a/2019/tests/samples/10-1-2.out b/2019/tests/samples/10-1-2.out deleted file mode 100644 index bb95160..0000000 --- a/2019/tests/samples/10-1-2.out +++ /dev/null @@ -1 +0,0 @@ -33 diff --git a/2019/tests/samples/10-1-3.in b/2019/tests/samples/10-1-3.in deleted file mode 100644 index e28e424..0000000 --- a/2019/tests/samples/10-1-3.in +++ /dev/null @@ -1,10 +0,0 @@ -#.#...#.#. -.###....#. -.#....#... -##.#.#.#.# -....#.#.#. -.##..###.# -..#...##.. -..##....## -......#... -.####.###. diff --git a/2019/tests/samples/10-1-3.out b/2019/tests/samples/10-1-3.out deleted file mode 100644 index 8f92bfd..0000000 --- a/2019/tests/samples/10-1-3.out +++ /dev/null @@ -1 +0,0 @@ -35 diff --git a/2019/tests/samples/10-1-4.in b/2019/tests/samples/10-1-4.in deleted file mode 100644 index af5b6e9..0000000 --- a/2019/tests/samples/10-1-4.in +++ /dev/null @@ -1,10 +0,0 @@ -.#..#..### -####.###.# -....###.#. -..###.##.# -##.##.#.#. -....###..# -..#.#..#.# -#..#.#.### -.##...##.# -.....#.#.. diff --git a/2019/tests/samples/10-1-4.out b/2019/tests/samples/10-1-4.out deleted file mode 100644 index 87523dd..0000000 --- a/2019/tests/samples/10-1-4.out +++ /dev/null @@ -1 +0,0 @@ -41 diff --git a/2019/tests/samples/10-1-5.in b/2019/tests/samples/10-1-5.in deleted file mode 100644 index 33437ba..0000000 --- a/2019/tests/samples/10-1-5.in +++ /dev/null @@ -1,20 +0,0 @@ -.#..##.###...####### -##.############..##. -.#.######.########.# -.###.#######.####.#. -#####.##.#.##.###.## -..#####..#.######### -#################### -#.####....###.#.#.## -##.################# -#####.##.###..####.. -..######..##.####### -####.##.####...##..# -.#####..#.######.### -##...#.##########... -#.##########.####### -.####.#.###.###.#.## -....##.##.###..##### -.#.#.###########.### -#.#.#.#####.####.### -###.##.####.##.#..## diff --git a/2019/tests/samples/10-1-5.out b/2019/tests/samples/10-1-5.out deleted file mode 100644 index cd7da05..0000000 --- a/2019/tests/samples/10-1-5.out +++ /dev/null @@ -1 +0,0 @@ -210 diff --git a/2019/tests/samples/12-2-1.in b/2019/tests/samples/12-2-1.in deleted file mode 100644 index 89cc805..0000000 --- a/2019/tests/samples/12-2-1.in +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/2019/tests/samples/12-2-1.out b/2019/tests/samples/12-2-1.out deleted file mode 100644 index f3f2632..0000000 --- a/2019/tests/samples/12-2-1.out +++ /dev/null @@ -1 +0,0 @@ -2772 diff --git a/2019/tests/samples/12-2-2.in b/2019/tests/samples/12-2-2.in deleted file mode 100644 index 1078293..0000000 --- a/2019/tests/samples/12-2-2.in +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/2019/tests/samples/12-2-2.out b/2019/tests/samples/12-2-2.out deleted file mode 100644 index f84ffdb..0000000 --- a/2019/tests/samples/12-2-2.out +++ /dev/null @@ -1 +0,0 @@ -4686774924 diff --git a/2019/tests/samples/14-1-1.in b/2019/tests/samples/14-1-1.in deleted file mode 100644 index 65ad5cc..0000000 --- a/2019/tests/samples/14-1-1.in +++ /dev/null @@ -1,6 +0,0 @@ -10 ORE => 10 A -1 ORE => 1 B -7 A, 1 B => 1 C -7 A, 1 C => 1 D -7 A, 1 D => 1 E -7 A, 1 E => 1 FUEL diff --git a/2019/tests/samples/14-1-1.out b/2019/tests/samples/14-1-1.out deleted file mode 100644 index e85087a..0000000 --- a/2019/tests/samples/14-1-1.out +++ /dev/null @@ -1 +0,0 @@ -31 diff --git a/2019/tests/samples/14-1-2.in b/2019/tests/samples/14-1-2.in deleted file mode 100644 index 85c4b1e..0000000 --- a/2019/tests/samples/14-1-2.in +++ /dev/null @@ -1,7 +0,0 @@ -9 ORE => 2 A -8 ORE => 3 B -7 ORE => 5 C -3 A, 4 B => 1 AB -5 B, 7 C => 1 BC -4 C, 1 A => 1 CA -2 AB, 3 BC, 4 CA => 1 FUEL diff --git a/2019/tests/samples/14-1-2.out b/2019/tests/samples/14-1-2.out deleted file mode 100644 index 9e42f3e..0000000 --- a/2019/tests/samples/14-1-2.out +++ /dev/null @@ -1 +0,0 @@ -165 diff --git a/2019/tests/samples/14-1-3.in b/2019/tests/samples/14-1-3.in deleted file mode 100644 index 4d6b9f0..0000000 --- a/2019/tests/samples/14-1-3.in +++ /dev/null @@ -1,9 +0,0 @@ -157 ORE => 5 NZVS -165 ORE => 6 DCFZ -44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL -12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ -179 ORE => 7 PSHF -177 ORE => 5 HKGWZ -7 DCFZ, 7 PSHF => 2 XJWVT -165 ORE => 2 GPVTF -3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT diff --git a/2019/tests/samples/14-1-3.out b/2019/tests/samples/14-1-3.out deleted file mode 100644 index ccb0cfe..0000000 --- a/2019/tests/samples/14-1-3.out +++ /dev/null @@ -1 +0,0 @@ -13312 diff --git a/2019/tests/samples/14-1-4.in b/2019/tests/samples/14-1-4.in deleted file mode 100644 index c670978..0000000 --- a/2019/tests/samples/14-1-4.in +++ /dev/null @@ -1,12 +0,0 @@ -2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG -17 NVRVD, 3 JNWZP => 8 VPVL -53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL -22 VJHF, 37 MNCFX => 5 FWMGM -139 ORE => 4 NVRVD -144 ORE => 7 JNWZP -5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC -5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV -145 ORE => 6 MNCFX -1 NVRVD => 8 CXFTF -1 VJHF, 6 MNCFX => 4 RFSQX -176 ORE => 6 VJHF diff --git a/2019/tests/samples/14-1-4.out b/2019/tests/samples/14-1-4.out deleted file mode 100644 index cb19a6c..0000000 --- a/2019/tests/samples/14-1-4.out +++ /dev/null @@ -1 +0,0 @@ -180697 diff --git a/2019/tests/samples/14-1-5.in b/2019/tests/samples/14-1-5.in deleted file mode 100644 index a5ca2c3..0000000 --- a/2019/tests/samples/14-1-5.in +++ /dev/null @@ -1,17 +0,0 @@ -171 ORE => 8 CNZTR -7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL -114 ORE => 4 BHXH -14 VRPVC => 6 BMBT -6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL -6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT -15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW -13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW -5 BMBT => 4 WPTQ -189 ORE => 9 KTJDG -1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP -12 VRPVC, 27 CNZTR => 2 XDBXC -15 KTJDG, 12 BHXH => 5 XCVML -3 BHXH, 2 VRPVC => 7 MZWV -121 ORE => 7 VRPVC -7 XCVML => 6 RJRHP -5 BHXH, 4 VRPVC => 5 LTCX diff --git a/2019/tests/samples/14-1-5.out b/2019/tests/samples/14-1-5.out deleted file mode 100644 index b65e868..0000000 --- a/2019/tests/samples/14-1-5.out +++ /dev/null @@ -1 +0,0 @@ -2210736 diff --git a/2019/tests/samples/14-2-1.in b/2019/tests/samples/14-2-1.in deleted file mode 120000 index e5a7725..0000000 --- a/2019/tests/samples/14-2-1.in +++ /dev/null @@ -1 +0,0 @@ -14-1-3.in \ No newline at end of file diff --git a/2019/tests/samples/14-2-1.out b/2019/tests/samples/14-2-1.out deleted file mode 100644 index 421714d..0000000 --- a/2019/tests/samples/14-2-1.out +++ /dev/null @@ -1 +0,0 @@ -82892753 diff --git a/2019/tests/samples/14-2-2.in b/2019/tests/samples/14-2-2.in deleted file mode 120000 index 78b977b..0000000 --- a/2019/tests/samples/14-2-2.in +++ /dev/null @@ -1 +0,0 @@ -14-1-4.in \ No newline at end of file diff --git a/2019/tests/samples/14-2-2.out b/2019/tests/samples/14-2-2.out deleted file mode 100644 index c55239b..0000000 --- a/2019/tests/samples/14-2-2.out +++ /dev/null @@ -1 +0,0 @@ -5586022 diff --git a/2019/tests/samples/14-2-3.in b/2019/tests/samples/14-2-3.in deleted file mode 120000 index 7e9ed9d..0000000 --- a/2019/tests/samples/14-2-3.in +++ /dev/null @@ -1 +0,0 @@ -14-1-5.in \ No newline at end of file diff --git a/2019/tests/samples/14-2-3.out b/2019/tests/samples/14-2-3.out deleted file mode 100644 index 1a5d12f..0000000 --- a/2019/tests/samples/14-2-3.out +++ /dev/null @@ -1 +0,0 @@ -460664 diff --git a/2019/tests/samples/16-1-1.in b/2019/tests/samples/16-1-1.in deleted file mode 100644 index a0d6069..0000000 --- a/2019/tests/samples/16-1-1.in +++ /dev/null @@ -1 +0,0 @@ -80871224585914546619083218645595 diff --git a/2019/tests/samples/16-1-1.out b/2019/tests/samples/16-1-1.out deleted file mode 100644 index e3a8042..0000000 --- a/2019/tests/samples/16-1-1.out +++ /dev/null @@ -1 +0,0 @@ -24176176 diff --git a/2019/tests/samples/16-1-2.in b/2019/tests/samples/16-1-2.in deleted file mode 100644 index e62b53a..0000000 --- a/2019/tests/samples/16-1-2.in +++ /dev/null @@ -1 +0,0 @@ -19617804207202209144916044189917 diff --git a/2019/tests/samples/16-1-2.out b/2019/tests/samples/16-1-2.out deleted file mode 100644 index a8ff9e0..0000000 --- a/2019/tests/samples/16-1-2.out +++ /dev/null @@ -1 +0,0 @@ -73745418 diff --git a/2019/tests/samples/16-1-3.in b/2019/tests/samples/16-1-3.in deleted file mode 100644 index fc400a2..0000000 --- a/2019/tests/samples/16-1-3.in +++ /dev/null @@ -1 +0,0 @@ -69317163492948606335995924319873 diff --git a/2019/tests/samples/16-1-3.out b/2019/tests/samples/16-1-3.out deleted file mode 100644 index 628d8a5..0000000 --- a/2019/tests/samples/16-1-3.out +++ /dev/null @@ -1 +0,0 @@ -52432133 diff --git a/2019/tests/samples/18-1-1.in b/2019/tests/samples/18-1-1.in deleted file mode 100644 index 33802e1..0000000 --- a/2019/tests/samples/18-1-1.in +++ /dev/null @@ -1,3 +0,0 @@ -######### -#b.A.@.a# -######### diff --git a/2019/tests/samples/18-1-1.out b/2019/tests/samples/18-1-1.out deleted file mode 100644 index 45a4fb7..0000000 --- a/2019/tests/samples/18-1-1.out +++ /dev/null @@ -1 +0,0 @@ -8 diff --git a/2019/tests/samples/18-1-2.in b/2019/tests/samples/18-1-2.in deleted file mode 100644 index af485bc..0000000 --- a/2019/tests/samples/18-1-2.in +++ /dev/null @@ -1,5 +0,0 @@ -######################## -#f.D.E.e.C.b.A.@.a.B.c.# -######################.# -#d.....................# -######################## diff --git a/2019/tests/samples/18-1-2.out b/2019/tests/samples/18-1-2.out deleted file mode 100644 index 8cf5c1a..0000000 --- a/2019/tests/samples/18-1-2.out +++ /dev/null @@ -1 +0,0 @@ -86 diff --git a/2019/tests/samples/18-1-3.in b/2019/tests/samples/18-1-3.in deleted file mode 100644 index b650235..0000000 --- a/2019/tests/samples/18-1-3.in +++ /dev/null @@ -1,5 +0,0 @@ -######################## -#...............b.C.D.f# -#.###################### -#.....@.a.B.c.d.A.e.F.g# -######################## diff --git a/2019/tests/samples/18-1-3.out b/2019/tests/samples/18-1-3.out deleted file mode 100644 index 94361d4..0000000 --- a/2019/tests/samples/18-1-3.out +++ /dev/null @@ -1 +0,0 @@ -132 diff --git a/2019/tests/samples/18-1-4.in b/2019/tests/samples/18-1-4.in deleted file mode 100644 index d5d888b..0000000 --- a/2019/tests/samples/18-1-4.in +++ /dev/null @@ -1,9 +0,0 @@ -################# -#i.G..c...e..H.p# -########.######## -#j.A..b...f..D.o# -########@######## -#k.E..a...g..B.n# -########.######## -#l.F..d...h..C.m# -################# diff --git a/2019/tests/samples/18-1-4.out b/2019/tests/samples/18-1-4.out deleted file mode 100644 index 7296f25..0000000 --- a/2019/tests/samples/18-1-4.out +++ /dev/null @@ -1 +0,0 @@ -136 diff --git a/2019/tests/samples/18-1-5.in b/2019/tests/samples/18-1-5.in deleted file mode 100644 index ee6598e..0000000 --- a/2019/tests/samples/18-1-5.in +++ /dev/null @@ -1,6 +0,0 @@ -######################## -#@..............ac.GI.b# -###d#e#f################ -###A#B#C################ -###g#h#i################ -######################## diff --git a/2019/tests/samples/18-1-5.out b/2019/tests/samples/18-1-5.out deleted file mode 100644 index d88e313..0000000 --- a/2019/tests/samples/18-1-5.out +++ /dev/null @@ -1 +0,0 @@ -81 diff --git a/2019/tests/samples/18-2-1.in b/2019/tests/samples/18-2-1.in deleted file mode 100644 index a2cfd7e..0000000 --- a/2019/tests/samples/18-2-1.in +++ /dev/null @@ -1,7 +0,0 @@ -############### -#d.ABC.#.....a# -######...###### -######.@.###### -######...###### -#b.....#.....c# -############### diff --git a/2019/tests/samples/18-2-1.out b/2019/tests/samples/18-2-1.out deleted file mode 100644 index a45fd52..0000000 --- a/2019/tests/samples/18-2-1.out +++ /dev/null @@ -1 +0,0 @@ -24 diff --git a/2019/tests/samples/20-1-1.in b/2019/tests/samples/20-1-1.in deleted file mode 100644 index 1e8d56f..0000000 --- a/2019/tests/samples/20-1-1.in +++ /dev/null @@ -1,19 +0,0 @@ - A - A - #######.######### - #######.........# - #######.#######.# - #######.#######.# - #######.#######.# - ##### B ###.# -BC...## C ###.# - ##.## ###.# - ##...DE F ###.# - ##### G ###.# - #########.#####.# -DE..#######...###.# - #.#########.###.# -FG..#########.....# - ###########.##### - Z - Z diff --git a/2019/tests/samples/20-1-1.out b/2019/tests/samples/20-1-1.out deleted file mode 100644 index 4099407..0000000 --- a/2019/tests/samples/20-1-1.out +++ /dev/null @@ -1 +0,0 @@ -23 diff --git a/2019/tests/samples/20-1-2.in b/2019/tests/samples/20-1-2.in deleted file mode 100644 index 6f61581..0000000 --- a/2019/tests/samples/20-1-2.in +++ /dev/null @@ -1,37 +0,0 @@ - A - A - #################.############# - #.#...#...................#.#.# - #.#.#.###.###.###.#########.#.# - #.#.#.......#...#.....#.#.#...# - #.#########.###.#####.#.#.###.# - #.............#.#.....#.......# - ###.###########.###.#####.#.#.# - #.....# A C #.#.#.# - ####### S P #####.# - #.#...# #......VT - #.#.#.# #.##### - #...#.# YN....#.# - #.###.# #####.# -DI....#.# #.....# - #####.# #.###.# -ZZ......# QG....#..AS - ###.### ####### -JO..#.#.# #.....# - #.#.#.# ###.#.# - #...#..DI BU....#..LF - #####.# #.##### -YN......# VT..#....QG - #.###.# #.###.# - #.#...# #.....# - ###.### J L J #.#.### - #.....# O F P #.#...# - #.###.#####.#.#####.#####.###.# - #...#.#.#...#.....#.....#.#...# - #.#####.###.###.#.#.#########.# - #...#.#.....#...#.#.#.#.....#.# - #.###.#####.###.###.#.#.####### - #.#.........#...#.............# - #########.###.###.############# - B J C - U P P diff --git a/2019/tests/samples/20-1-2.out b/2019/tests/samples/20-1-2.out deleted file mode 100644 index 8c61d23..0000000 --- a/2019/tests/samples/20-1-2.out +++ /dev/null @@ -1 +0,0 @@ -58 diff --git a/2019/tests/samples/20-2-2.in b/2019/tests/samples/20-2-2.in deleted file mode 100644 index d051133..0000000 --- a/2019/tests/samples/20-2-2.in +++ /dev/null @@ -1,37 +0,0 @@ - Z L X W C - Z P Q B K - ###########.#.#.#.#######.############### - #...#.......#.#.......#.#.......#.#.#...# - ###.#.#.#.#.#.#.#.###.#.#.#######.#.#.### - #.#...#.#.#...#.#.#...#...#...#.#.......# - #.###.#######.###.###.#.###.###.#.####### - #...#.......#.#...#...#.............#...# - #.#########.#######.#.#######.#######.### - #...#.# F R I Z #.#.#.# - #.###.# D E C H #.#.#.# - #.#...# #...#.# - #.###.# #.###.# - #.#....OA WB..#.#..ZH - #.###.# #.#.#.# -CJ......# #.....# - ####### ####### - #.#....CK #......IC - #.###.# #.###.# - #.....# #...#.# - ###.### #.#.#.# -XF....#.# RF..#.#.# - #####.# ####### - #......CJ NM..#...# - ###.#.# #.###.# -RE....#.# #......RF - ###.### X X L #.#.#.# - #.....# F Q P #.#.#.# - ###.###########.###.#######.#########.### - #.....#...#.....#.......#...#.....#.#...# - #####.#.###.#######.#######.###.###.#.#.# - #.......#.......#.#.#.#.#...#...#...#.#.# - #####.###.#####.#.#.#.#.###.###.#.###.### - #.......#.....#.#...#...............#...# - #############.#.#.###.################### - A O F N - A A D M diff --git a/2019/tests/samples/20-2-2.out b/2019/tests/samples/20-2-2.out deleted file mode 100644 index 4391a33..0000000 --- a/2019/tests/samples/20-2-2.out +++ /dev/null @@ -1 +0,0 @@ -396 diff --git a/2019/tests/samples/24-1-1.in b/2019/tests/samples/24-1-1.in deleted file mode 100644 index 704a112..0000000 --- a/2019/tests/samples/24-1-1.in +++ /dev/null @@ -1,5 +0,0 @@ -....# -#..#. -#..## -..#.. -#.... diff --git a/2019/tests/samples/24-1-1.out b/2019/tests/samples/24-1-1.out deleted file mode 100644 index 39f6036..0000000 --- a/2019/tests/samples/24-1-1.out +++ /dev/null @@ -1 +0,0 @@ -2129920 diff --git a/2019/tests/test_intcode.cpp b/2019/tests/test_intcode.cpp deleted file mode 100644 index c9adc85..0000000 --- a/2019/tests/test_intcode.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include "utils.hpp" - -using aoc2019::run_intcode; -using aoc2019::IntCodeComputer; - -auto run_program(std::vector program, std::deque input) { - std::deque output; - IntCodeComputer computer(std::move(program), std::move(input)); - computer.connectOutput(output); - computer.run(); - return output; -} - -TEST(Intcode, TestReproduceInput) { - const std::vector program = {109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99}; - const std::deque expected(program.begin(), program.end()); - - ASSERT_EQ(expected, run_program(program, {})); -} - -TEST(Intcode, TestLargeMultiplication) { - const std::vector program = {1102, 34915192, 34915192, 7, 4, 7, 99, 0}; - - ASSERT_EQ(1219070632396864, run_program(program, {}).front()); -} - -TEST(Intcode, TestLargeNumber) { - const std::vector program = {104, 1125899906842624, 99}; - - ASSERT_EQ(1125899906842624, run_program(program, {}).front()); -} - -TEST(Intcode, TestPositionEquality) { - const std::vector program = {3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8}; - - ASSERT_EQ(1, run_program(program, {8}).front()); - ASSERT_EQ(0, run_program(program, {9}).front()); -} - -TEST(Intcode, TestPositionLess) { - const std::vector program = {3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8}; - - ASSERT_EQ(1, run_program(program, {7}).front()); - ASSERT_EQ(0, run_program(program, {9}).front()); -} - -TEST(Intcode, TestImmediateEquality) { - const std::vector program = {3, 3, 1108, -1, 8, 3, 4, 3, 99}; - - ASSERT_EQ(1, run_program(program, {8}).front()); - ASSERT_EQ(0, run_program(program, {9}).front()); -} - -TEST(Intcode, TestImmediateLess) { - const std::vector program = {3, 3, 1107, -1, 8, 3, 4, 3, 99}; - - ASSERT_EQ(1, run_program(program, {7}).front()); - ASSERT_EQ(0, run_program(program, {9}).front()); -} - -TEST(Intcode, TestComplicatedConditional) { - const std::vector program = {3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, - 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, - 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99}; - auto pcopy = program; - - auto output = run_intcode(pcopy, {7}); - ASSERT_EQ(999, output.front()); - - pcopy = program; - output = run_intcode(pcopy, {9}); - ASSERT_EQ(1001, output.front()); - - pcopy = program; - output = run_intcode(pcopy, {8}); - ASSERT_EQ(1000, output.front()); -} diff --git a/2019/tests/test_solutions.cpp b/2019/tests/test_solutions.cpp deleted file mode 100644 index ea870bc..0000000 --- a/2019/tests/test_solutions.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "implementations.hpp" - -class SolutionsTest : public testing::TestWithParam { -public: - static std::string nameInstantiatedTest(const testing::TestParamInfo ¶mInfo); - -protected: - std::string input_data = ""; - std::string output_data = ""; - aoc2019::solution_t implementation = nullptr; - - // Read input data - void SetUp() override; - -private: - static void readToString(const std::string &name, std::string &target); - - static std::tuple parseInputName(const std::string &name); -}; - -void SolutionsTest::SetUp() { - const auto input_name = GetParam(); - const auto output_name = input_name.substr(0, input_name.length() - 3) + ".out"; - - int day; - bool part2; - std::tie(day, part2, std::ignore) = parseInputName(input_name); - implementation = aoc2019::get_implementation(day, part2); - - readToString(input_name, input_data); - readToString(output_name, output_data); -} - -void SolutionsTest::readToString(const std::string &name, std::string &target) { - std::ifstream source(name); - - target.assign(std::istreambuf_iterator(source), - std::istreambuf_iterator()); -} - -std::tuple SolutionsTest::parseInputName(const std::string &name) { - const char *base_name = name.c_str(); - if (const auto last_slash = name.rfind('/'); last_slash != std::string::npos) { - base_name += last_slash + 1; - } - int day, part; - auto res = std::from_chars(base_name, base_name + 2, day); - assert(res.ec == std::errc()); - res = std::from_chars(base_name + 3, base_name + 4, part); - assert(res.ec == std::errc()); - - return {day, part == 2, std::string(base_name + 5, (const char*) std::strchr(base_name, '.'))}; -} - -std::string SolutionsTest::nameInstantiatedTest(const testing::TestParamInfo ¶mInfo) { - int day; - bool part2; - std::string sampleName; - - std::tie(day, part2, sampleName) = parseInputName(paramInfo.param); - - std::stringstream nameBuilder; - - nameBuilder << "Day" << day << "Part" << (part2 ? 2 : 1) << "Sample"; - - std::copy_if(sampleName.cbegin(), sampleName.cend(), std::ostream_iterator(nameBuilder), [](char c) { - return std::isalnum(c); - }); - - return nameBuilder.str(); -} - -TEST_P(SolutionsTest, TestExpectedOutcome) { - std::stringstream input_buffer, output_buffer; - - // Sanity check, don't call null implementation - ASSERT_NE(implementation, nullptr); - - input_buffer.str(input_data); - - implementation(input_buffer, output_buffer); - - ASSERT_EQ(output_data, output_buffer.str()); -} - -static std::vector get_samples() { - std::vector samples; - for (const auto &entry : std::filesystem::directory_iterator(TEST_SAMPLES_DIR)) { - if (entry.path().filename().extension() == ".in") { - samples.push_back(entry.path().string()); - } - } - - // Ensure a consistent order. - std::sort(samples.begin(), samples.end()); - - return samples; -} - -INSTANTIATE_TEST_CASE_P(DaysTest, SolutionsTest, - testing::ValuesIn(get_samples()), - SolutionsTest::nameInstantiatedTest); From 07db73aa3edbd11324454dd4567dfd5e589fcbe1 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 15:52:12 +0100 Subject: [PATCH 02/37] Implement 2019 day 1 with tests in Python --- 2019/.gitignore | 141 +++++++++++++++++++++++++++++++++++++++ 2019/README.md | 8 +++ 2019/aoc2019/__init__.py | 0 2019/aoc2019/__main__.py | 28 ++++++++ 2019/aoc2019/day01.py | 23 +++++++ 2019/requirements.txt | 1 + 2019/tests/__init__.py | 0 2019/tests/test_day01.py | 22 ++++++ 8 files changed, 223 insertions(+) create mode 100644 2019/README.md create mode 100644 2019/aoc2019/__init__.py create mode 100644 2019/aoc2019/__main__.py create mode 100644 2019/aoc2019/day01.py create mode 100644 2019/requirements.txt create mode 100644 2019/tests/__init__.py create mode 100644 2019/tests/test_day01.py diff --git a/2019/.gitignore b/2019/.gitignore index e69de29..a1ce8e7 100644 --- a/2019/.gitignore +++ b/2019/.gitignore @@ -0,0 +1,141 @@ +# Virtual environment +venv + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/2019/README.md b/2019/README.md new file mode 100644 index 0000000..6c7fb91 --- /dev/null +++ b/2019/README.md @@ -0,0 +1,8 @@ +# Advent of Code 2019 + +This is a quick-and-dirty implementation of all 2019 problems implemented in +Python because I got fed up with C++ and really couldn't stand the missing +stars on the [events page](https://adventofcode.com/2020/events). + +I'll try to incorporate unit tests and all because it's just nice programming, +but this edition has decidedly less polish than my other attempts. diff --git a/2019/aoc2019/__init__.py b/2019/aoc2019/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/2019/aoc2019/__main__.py b/2019/aoc2019/__main__.py new file mode 100644 index 0000000..50b3aec --- /dev/null +++ b/2019/aoc2019/__main__.py @@ -0,0 +1,28 @@ +import argparse +import importlib +import sys + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('day', type=int) + parser.add_argument('input', type=argparse.FileType('rt'), nargs='?', default=sys.stdin) + parser.add_argument('-2', '--part2', action='store_true') + + args = parser.parse_args() + + try: + day = importlib.import_module(f'.day{args.day:02d}', __package__) + + if args.part2: + function = day.part2 + else: + function = day.part1 + + print(function(args.input)) + + except ImportError: + sys.exit(f'Invalid day: {args.day}') + + +main() diff --git a/2019/aoc2019/day01.py b/2019/aoc2019/day01.py new file mode 100644 index 0000000..ac06f40 --- /dev/null +++ b/2019/aoc2019/day01.py @@ -0,0 +1,23 @@ +from typing import TextIO + + +def fuel_required(weight: int) -> int: + return max(0, weight // 3 - 2) + + +def recursive_fuel_required(weight: int) -> int: + total = 0 + + while weight > 0: + weight = fuel_required(weight) + total += weight + + return total + + +def part1(data: TextIO) -> int: + return sum(fuel_required(int(line)) for line in data) + + +def part2(data: TextIO) -> int: + return sum(recursive_fuel_required(int(line)) for line in data) diff --git a/2019/requirements.txt b/2019/requirements.txt new file mode 100644 index 0000000..e079f8a --- /dev/null +++ b/2019/requirements.txt @@ -0,0 +1 @@ +pytest diff --git a/2019/tests/__init__.py b/2019/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/2019/tests/test_day01.py b/2019/tests/test_day01.py new file mode 100644 index 0000000..2eaf866 --- /dev/null +++ b/2019/tests/test_day01.py @@ -0,0 +1,22 @@ +from aoc2019.day01 import fuel_required, recursive_fuel_required + +import pytest + + +@pytest.mark.parametrize('weight,required', [ + (12, 2), + (14, 2), + (1969, 654), + (100756, 33583) +]) +def test_fuel_required(weight: int, required: int) -> None: + assert fuel_required(weight) == required + + +@pytest.mark.parametrize('weight,required', [ + (14, 2), + (1969, 966), + (100756, 50346) +]) +def test_fuel_required_recursive(weight: int, required: int) -> None: + assert recursive_fuel_required(weight) == required From 07e869c4973fd7debe90255a78058c7215a2a973 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 16:02:44 +0100 Subject: [PATCH 03/37] Set up travis for use with Python --- .travis.yml | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index d25ca21..98e209c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,24 @@ dist: bionic -language: rust -rust: - - stable - - beta - - nightly +language: python + +python: + - "3.9" + - "nightly" jobs: allow_failures: - - rust: nightly + - python: nightly fast_finish: true -cache: - - cargo - - 2020/target - # Custom directory, for the correct year -before_script: - - cd 2020 +before_install: + - cd 2019 + - python -m pip install --upgrade pip + +script: pytest + +cache: + directories: + - $HOME/.cache/pip +before_cache: + - rm -f $HOME/.cache/pip/log/debug.log From 930d86404d59a4392bdf5db16b30b777cc6e0a42 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 17:05:10 +0100 Subject: [PATCH 04/37] Implement 2019 day 2 Start of the intcode madness --- 2019/aoc2019/day02.py | 33 +++++++++++++++++++++ 2019/aoc2019/intcode.py | 59 ++++++++++++++++++++++++++++++++++++++ 2019/tests/test_intcode.py | 20 +++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 2019/aoc2019/day02.py create mode 100644 2019/aoc2019/intcode.py create mode 100644 2019/tests/test_intcode.py diff --git a/2019/aoc2019/day02.py b/2019/aoc2019/day02.py new file mode 100644 index 0000000..e1fa544 --- /dev/null +++ b/2019/aoc2019/day02.py @@ -0,0 +1,33 @@ +from typing import TextIO + +from aoc2019.intcode import read_program, Computer + + +def part1(data: TextIO) -> int: + program = read_program(data) + + program[1] = 12 + program[2] = 2 + + computer = Computer(program) + computer.run() + + return computer[0] + + +def part2(data: TextIO) -> int: + program = read_program(data) + + for verb in range(100): + for noun in range(100): + computer = Computer(program.copy()) + + computer[1] = noun + computer[2] = verb + + computer.run() + + if computer[0] == 19690720: + return 100 * noun + verb + + raise ValueError('Did not find valid combination') diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py new file mode 100644 index 0000000..e92fcb2 --- /dev/null +++ b/2019/aoc2019/intcode.py @@ -0,0 +1,59 @@ +from typing import List, TextIO + + +def read_program(data: TextIO) -> List[int]: + line = next(data) + + return [int(i) for i in line.split(',')] + + +class Computer: + program: List[int] + pointer: int + + def __init__(self, program: List[int], pointer: int = 0) -> None: + self.program = program + self.pointer = pointer + + def __getitem__(self, item: int) -> int: + self._ensure_length(item + 1) + return self.program[item] + + def __setitem__(self, key: int, value: int) -> None: + self._ensure_length(key + 1) + self.program[key] = value + + def _ensure_length(self, length: int) -> None: + if len(self.program) < length: + # Double current program size with 0s + self.program.extend(0 for _ in range(len(self.program))) + + def run(self) -> None: + """ Run until failure""" + while self._execute_current(): + pass + + def _execute_current(self) -> bool: + """ + Execute a single instruction + :return: True if the program should continue + """ + pointer = self.pointer + opcode = self[pointer] + + if opcode == 1: + # Add + self[self[pointer + 3]] = self[self[pointer + 1]] + self[self[pointer + 2]] + self.pointer += 4 + elif opcode == 2: + # Multiply + self[self[pointer + 3]] = self[self[pointer + 1]] * self[self[pointer + 2]] + self.pointer += 4 + elif opcode == 99: + # Halt + return False + else: + raise ValueError(f'Unknown opcode {opcode} at {pointer}') + + return True + diff --git a/2019/tests/test_intcode.py b/2019/tests/test_intcode.py new file mode 100644 index 0000000..670b58c --- /dev/null +++ b/2019/tests/test_intcode.py @@ -0,0 +1,20 @@ +from typing import List + +import pytest + +from aoc2019.intcode import Computer + + +@pytest.mark.parametrize('program,expected', [ + ([1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50], [3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50]), + ([1, 0, 0, 0, 99], [2, 0, 0, 0, 99]), + ([2, 3, 0, 3, 99], [2, 3, 0, 6, 99]), + ([2, 4, 4, 5, 99, 0], [2, 4, 4, 5, 99, 9801]), + ([1, 1, 1, 4, 99, 5, 6, 0, 99], [30, 1, 1, 4, 2, 5, 6, 0, 99]) +]) +def test_instructions_day2(program: List[int], expected: List[int]) -> None: + computer = Computer(program) + + computer.run() + + assert computer.program == expected From 7a292b026dabe6bea58b7733374475295df56211 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 17:30:37 +0100 Subject: [PATCH 05/37] Implement 2019 day 3 --- 2019/aoc2019/day03.py | 44 ++++++++++++++++++++++++++++++++++++++++ 2019/tests/test_day03.py | 25 +++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 2019/aoc2019/day03.py create mode 100644 2019/tests/test_day03.py diff --git a/2019/aoc2019/day03.py b/2019/aoc2019/day03.py new file mode 100644 index 0000000..9c0c272 --- /dev/null +++ b/2019/aoc2019/day03.py @@ -0,0 +1,44 @@ +import itertools +from typing import Dict, TextIO + + +def compute_points(line: str) -> Dict[complex, int]: + points: Dict[complex, int] = {} + steps = itertools.count(1) + + pos = complex(0) + + directions = { + 'U': 1j, + 'R': 1, + 'D': -1j, + 'L': -1, + } + + for move in line.strip().split(','): + direction = directions[move[0]] + + for _ in range(int(move[1:])): + pos += direction + + points.setdefault(pos, next(steps)) + + return points + + +def part1(data: TextIO) -> int: + points_a = compute_points(next(data)) + points_b = compute_points(next(data)) + + in_common = set(points_a.keys()) & set(points_b.keys()) + + return int(min(abs(c.imag) + abs(c.real) for c in in_common)) + + +def part2(data: TextIO) -> int: + points_a = compute_points(next(data)) + points_b = compute_points(next(data)) + + in_common = set(points_a.keys()) & set(points_b.keys()) + + return min(points_a[pos] + points_b[pos] for pos in in_common) diff --git a/2019/tests/test_day03.py b/2019/tests/test_day03.py new file mode 100644 index 0000000..7a691ae --- /dev/null +++ b/2019/tests/test_day03.py @@ -0,0 +1,25 @@ +from io import StringIO + +import pytest + +from aoc2019.day03 import part1, part2 + +SAMPLES = [ + "R8,U5,L5,D3\nU7,R6,D4,L4", + "R75,D30,R83,U83,L12,D49,R71,U7,L72\nU62,R66,U55,R34,D71,R55,D58,R83", + "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51\nU98,R91,D20,R16,D67,R40,U7,R15,U6,R7", +] + + +@pytest.mark.parametrize('paths,outcome', zip(SAMPLES, [6, 159, 135])) +def test_part1(paths: str, outcome: int): + path_data = StringIO(paths) + + assert part1(path_data) == outcome + + +@pytest.mark.parametrize('paths,outcome', zip(SAMPLES, [30, 610, 410])) +def test_part2(paths: str, outcome: int): + path_data = StringIO(paths) + + assert part2(path_data) == outcome From ad3029759a1df71c4bd73584c4d2e809fc25c3f0 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 17:52:59 +0100 Subject: [PATCH 06/37] Implement 2019 day 4 --- 2019/aoc2019/day04.py | 38 ++++++++++++++++++++++++++++++++++++++ 2019/tests/test_day04.py | 17 +++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 2019/aoc2019/day04.py create mode 100644 2019/tests/test_day04.py diff --git a/2019/aoc2019/day04.py b/2019/aoc2019/day04.py new file mode 100644 index 0000000..87cf039 --- /dev/null +++ b/2019/aoc2019/day04.py @@ -0,0 +1,38 @@ +import itertools +from typing import TextIO + + +def read_range(data: TextIO) -> range: + a, b = next(data).split('-') + + return range(int(a), int(b) + 1) # plus one because inclusive + + +def valid(number: int, strict: bool) -> bool: + s = str(number) + prev = '/' # is smaller than '0' + has_group = False + + if len(s) != 6: + return False + + for k, g in itertools.groupby(s): + if k < prev: + return False + + prev = k + + amount = sum(1 for _ in g) + + if amount == 2 or not strict and amount > 2: + has_group = True + + return has_group + + +def part1(data: TextIO) -> int: + return sum(1 for password in read_range(data) if valid(password, False)) + + +def part2(data: TextIO) -> int: + return sum(1 for password in read_range(data) if valid(password, True)) diff --git a/2019/tests/test_day04.py b/2019/tests/test_day04.py new file mode 100644 index 0000000..3d3248a --- /dev/null +++ b/2019/tests/test_day04.py @@ -0,0 +1,17 @@ +import pytest + +from aoc2019.day04 import valid + + +@pytest.mark.parametrize('number,strict,expected', [ + (122345, False, True), + (111123, False, True), + (111111, False, True), + (223450, False, False), + (123789, False, False), + (112233, True, True), + (123444, True, False), + (111122, True, True) +]) +def test_valid(number: int, strict: bool, expected: bool) -> None: + assert valid(number, strict) == expected From b18945c44dd36ddb6830446306272073c0c64e14 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 19:57:36 +0100 Subject: [PATCH 07/37] Implement 2019 day 5 part 1 --- 2019/aoc2019/day05.py | 29 +++++++++++++++++ 2019/aoc2019/intcode.py | 65 +++++++++++++++++++++++++++++++------- 2019/tests/test_intcode.py | 4 ++- 3 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 2019/aoc2019/day05.py diff --git a/2019/aoc2019/day05.py b/2019/aoc2019/day05.py new file mode 100644 index 0000000..ce52d26 --- /dev/null +++ b/2019/aoc2019/day05.py @@ -0,0 +1,29 @@ +from typing import TextIO + +from aoc2019.intcode import read_program, Computer + + +def part1(data: TextIO) -> int: + program = read_program(data) + + computer = Computer(program) + + # Enter the required starting code + computer.input.append(1) + + computer.run() + + return computer.output.pop() + + +def part2(data: TextIO) -> int: + program = read_program(data) + + computer = Computer(program) + + # Enter the required starting code + computer.input.append(5) + + computer.run() + + return computer.output.pop() diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index e92fcb2..3744731 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -1,4 +1,5 @@ -from typing import List, TextIO +import collections +from typing import List, TextIO, Tuple, Union def read_program(data: TextIO) -> List[int]: @@ -10,18 +11,46 @@ def read_program(data: TextIO) -> List[int]: class Computer: program: List[int] pointer: int + input: collections.deque[int] + output: collections.deque[int] def __init__(self, program: List[int], pointer: int = 0) -> None: self.program = program self.pointer = pointer + self.input = collections.deque() + self.output = collections.deque() - def __getitem__(self, item: int) -> int: - self._ensure_length(item + 1) - return self.program[item] + def _mode_and_key(self, item: Union[int, Tuple[int, int]]) -> Tuple[int, int]: + if type(item) == int: + mode = 0 + key = item + else: + mode, key = item + key = self.program[self.pointer + key] - def __setitem__(self, key: int, value: int) -> None: - self._ensure_length(key + 1) - self.program[key] = value + return mode, key + + def __getitem__(self, item: Union[int, Tuple[int, int]]) -> int: + mode, key = self._mode_and_key(item) + + if mode == 0: + self._ensure_length(key + 1) + return self.program[key] + elif mode == 1: + return key + else: + raise ValueError(f'Unsupported mode "{mode}"') + + def __setitem__(self, item: Union[int, Tuple[int, int]], value: int) -> None: + mode, key = self._mode_and_key(item) + + if mode == 0: + self._ensure_length(key + 1) + self.program[key] = value + elif mode == 1: + raise ValueError('Cannot assign to an immediate') + else: + raise ValueError(f'Unsupported mode "{mode}"') def _ensure_length(self, length: int) -> None: if len(self.program) < length: @@ -29,7 +58,7 @@ class Computer: self.program.extend(0 for _ in range(len(self.program))) def run(self) -> None: - """ Run until failure""" + """ Run until failure """ while self._execute_current(): pass @@ -39,16 +68,30 @@ class Computer: :return: True if the program should continue """ pointer = self.pointer - opcode = self[pointer] + instruction = self[pointer] + opcode = instruction % 100 + + mode = [ + (instruction // 100) % 10, + (instruction // 1000) % 10, + (instruction // 10000) % 10, + ] if opcode == 1: # Add - self[self[pointer + 3]] = self[self[pointer + 1]] + self[self[pointer + 2]] + self[mode[2], 3] = self[mode[0], 1] + self[mode[1], 2] self.pointer += 4 elif opcode == 2: # Multiply - self[self[pointer + 3]] = self[self[pointer + 1]] * self[self[pointer + 2]] + self[mode[2], 3] = self[mode[0], 1] * self[mode[1], 2] self.pointer += 4 + elif opcode == 3: + # Input + self[mode[0], 1] = self.input.popleft() + self.pointer += 2 + elif opcode == 4: + self.output.append(self[mode[0], 1]) + self.pointer += 2 elif opcode == 99: # Halt return False diff --git a/2019/tests/test_intcode.py b/2019/tests/test_intcode.py index 670b58c..0148476 100644 --- a/2019/tests/test_intcode.py +++ b/2019/tests/test_intcode.py @@ -10,7 +10,9 @@ from aoc2019.intcode import Computer ([1, 0, 0, 0, 99], [2, 0, 0, 0, 99]), ([2, 3, 0, 3, 99], [2, 3, 0, 6, 99]), ([2, 4, 4, 5, 99, 0], [2, 4, 4, 5, 99, 9801]), - ([1, 1, 1, 4, 99, 5, 6, 0, 99], [30, 1, 1, 4, 2, 5, 6, 0, 99]) + ([1, 1, 1, 4, 99, 5, 6, 0, 99], [30, 1, 1, 4, 2, 5, 6, 0, 99]), + # This is technically part of day 5 but it fits the pattern + ([1002, 4, 3, 4, 33], [1002, 4, 3, 4, 99]) ]) def test_instructions_day2(program: List[int], expected: List[int]) -> None: computer = Computer(program) From 07098ab691e3492cddaf2f6df16705cb2ab11bdb Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 20:27:30 +0100 Subject: [PATCH 08/37] Implement 2019 day 5 part 2 --- 2019/aoc2019/intcode.py | 27 +++++++++++++++++++++++ 2019/tests/test_intcode.py | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index 3744731..206fef4 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -90,8 +90,35 @@ class Computer: self[mode[0], 1] = self.input.popleft() self.pointer += 2 elif opcode == 4: + # Output self.output.append(self[mode[0], 1]) self.pointer += 2 + elif opcode == 5: + # Jump if true + if self[mode[0], 1] != 0: + self.pointer = self[mode[1], 2] + else: + self.pointer += 3 + elif opcode == 6: + # Jump if false + if self[mode[0], 1] == 0: + self.pointer = self[mode[1], 2] + else: + self.pointer += 3 + elif opcode == 7: + # Less than + if self[mode[0], 1] < self[mode[1], 2]: + self[mode[2], 3] = 1 + else: + self[mode[2], 3] = 0 + self.pointer += 4 + elif opcode == 8: + # Equals + if self[mode[0], 1] == self[mode[1], 2]: + self[mode[2], 3] = 1 + else: + self[mode[2], 3] = 0 + self.pointer += 4 elif opcode == 99: # Halt return False diff --git a/2019/tests/test_intcode.py b/2019/tests/test_intcode.py index 0148476..ea4cbf5 100644 --- a/2019/tests/test_intcode.py +++ b/2019/tests/test_intcode.py @@ -1,3 +1,4 @@ +import itertools from typing import List import pytest @@ -20,3 +21,46 @@ def test_instructions_day2(program: List[int], expected: List[int]) -> None: computer.run() assert computer.program == expected + + +@pytest.mark.parametrize('number,program', itertools.product([7, 8, 9], [ + [3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8], + [3, 3, 1108, -1, 8, 3, 4, 3, 99], +])) +def test_equality_opcode(program: List[int], number: int): + computer = Computer(program.copy()) + computer.input.append(number) + + computer.run() + + assert computer.output.pop() == int(number == 8) + + +@pytest.mark.parametrize('number,program', itertools.product([7, 8, 9], [ + [3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8], + [3, 3, 1107, -1, 8, 3, 4, 3, 99], +])) +def test_less_than_opcode(program: List[int], number: int): + computer = Computer(program.copy()) + computer.input.append(number) + + computer.run() + + assert computer.output.pop() == int(number < 8) + + +@pytest.mark.parametrize('inputs,expected', [ + (12, 1001), + (8, 1000), + (2, 999), +]) +def test_day5_example(inputs: int, expected: int): + computer = Computer([3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, + 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, + 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99]) + + computer.input.append(inputs) + + computer.run() + + assert computer.output.pop() == expected From fe639f14b3c5c345bd555bfd400317133d3fb3a0 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 21:08:27 +0100 Subject: [PATCH 09/37] Implement 2019 day 6 --- 2019/aoc2019/day06.py | 27 +++++++++++++++++++++++++++ 2019/requirements.txt | 1 + 2019/tests/test_day6.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 2019/aoc2019/day06.py create mode 100644 2019/tests/test_day6.py diff --git a/2019/aoc2019/day06.py b/2019/aoc2019/day06.py new file mode 100644 index 0000000..f35a7aa --- /dev/null +++ b/2019/aoc2019/day06.py @@ -0,0 +1,27 @@ +from typing import TextIO + +import networkx + + +def read_graph(data: TextIO) -> networkx.DiGraph: + graph = networkx.DiGraph() + + for line in data: + a, b = line.strip().split(')') + graph.add_edge(a, b) + + return graph + + +def part1(data: TextIO) -> int: + graph = read_graph(data) + + paths = networkx.single_source_shortest_path_length(graph, 'COM') + + return sum(paths.values()) + + +def part2(data: TextIO) -> int: + graph = read_graph(data).to_undirected() + + return networkx.shortest_path_length(graph, 'YOU', 'SAN') - 2 diff --git a/2019/requirements.txt b/2019/requirements.txt index e079f8a..5ff3949 100644 --- a/2019/requirements.txt +++ b/2019/requirements.txt @@ -1 +1,2 @@ pytest +networkx diff --git a/2019/tests/test_day6.py b/2019/tests/test_day6.py new file mode 100644 index 0000000..e3839a2 --- /dev/null +++ b/2019/tests/test_day6.py @@ -0,0 +1,39 @@ +from io import StringIO + +from aoc2019.day06 import part1, part2 + + +def test_sample_part1(): + data = StringIO("""\ + COM)B + B)C + C)D + D)E + E)F + B)G + G)H + D)I + E)J + J)K + K)L""") + + assert part1(data) == 42 + + +def test_sample_part2(): + data = StringIO("""\ + COM)B + B)C + C)D + D)E + E)F + B)G + G)H + D)I + E)J + J)K + K)L + K)YOU + I)SAN""") + + assert part2(data) == 4 From 18351f93ebe3b080ba651bab5fc048ad46b394b8 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 21:33:10 +0100 Subject: [PATCH 10/37] Implement 2019 day 7 --- 2019/aoc2019/day07.py | 69 ++++++++++++++++++++++ 2019/tests/{test_day6.py => test_day06.py} | 0 2019/tests/test_day07.py | 27 +++++++++ 3 files changed, 96 insertions(+) create mode 100644 2019/aoc2019/day07.py rename 2019/tests/{test_day6.py => test_day06.py} (100%) create mode 100644 2019/tests/test_day07.py diff --git a/2019/aoc2019/day07.py b/2019/aoc2019/day07.py new file mode 100644 index 0000000..b923273 --- /dev/null +++ b/2019/aoc2019/day07.py @@ -0,0 +1,69 @@ +import itertools +from typing import List, TextIO, Tuple + +from aoc2019.intcode import read_program, Computer + + +def amplify(phases: Tuple[int], program: List[int]) -> int: + amps = [] + + for i, phase in enumerate(phases): + amp = Computer(program.copy()) + + if i > 0: + amp.input = amps[i - 1].output + + amp.input.append(phase) + + amps.append(amp) + + amps[0].input.append(0) + + for amp in amps: + amp.run() + + return amps[-1].output.pop() + + +def reamplify(phases: Tuple[int], program: List[int]) -> int: + amps = [] + + for i, _ in enumerate(phases): + amp = Computer(program.copy()) + + if i > 0: + amp.input = amps[i - 1].output + + amps.append(amp) + + amps[0].input = amps[-1].output + + for amp, phase in zip(amps, phases): + amp.input.append(phase) + + amps[0].input.append(0) + + changes = True + + while changes: + changes = False + for amp in amps: + try: + amp.run() + except IndexError: + # Waiting for input + changes = True + + return amps[-1].output.pop() + + +def part1(data: TextIO) -> int: + program = read_program(data) + + return max(amplify(phase, program) for phase in itertools.permutations(range(0, 5))) + + +def part2(data: TextIO) -> int: + program = read_program(data) + + return max(reamplify(phase, program) for phase in itertools.permutations(range(5, 10))) diff --git a/2019/tests/test_day6.py b/2019/tests/test_day06.py similarity index 100% rename from 2019/tests/test_day6.py rename to 2019/tests/test_day06.py diff --git a/2019/tests/test_day07.py b/2019/tests/test_day07.py new file mode 100644 index 0000000..76af1c7 --- /dev/null +++ b/2019/tests/test_day07.py @@ -0,0 +1,27 @@ +from io import StringIO + +import pytest + +from aoc2019.day07 import part1, part2 + + +@pytest.mark.parametrize('maximum,program', [ + (43210, "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0"), + (54321, "3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0"), + (65210, "3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0"), +]) +def test_sample_part1(maximum: int, program: str) -> None: + data = StringIO(program) + + assert part1(data) == maximum + + +@pytest.mark.parametrize('maximum,program', [ + (139629729, "3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5"), + (18216, "3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54," + "53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10"), +]) +def test_sample_part2(maximum: int, program: str) -> None: + data = StringIO(program) + + assert part2(data) == maximum From 4418292dc4ccd3cae4c414263900351d644a0496 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 23 Jan 2021 22:34:58 +0100 Subject: [PATCH 11/37] Implement 2019 day 8 --- 2019/aoc2019/__main__.py | 4 ++-- 2019/aoc2019/day06.py | 2 +- 2019/aoc2019/day07.py | 8 ++++---- 2019/aoc2019/day08.py | 33 +++++++++++++++++++++++++++++++++ 2019/aoc2019/intcode.py | 9 +++------ 2019/requirements.txt | 1 + 6 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 2019/aoc2019/day08.py diff --git a/2019/aoc2019/__main__.py b/2019/aoc2019/__main__.py index 50b3aec..91147cf 100644 --- a/2019/aoc2019/__main__.py +++ b/2019/aoc2019/__main__.py @@ -15,9 +15,9 @@ def main() -> None: day = importlib.import_module(f'.day{args.day:02d}', __package__) if args.part2: - function = day.part2 + function = day.part2 # type: ignore else: - function = day.part1 + function = day.part1 # type: ignore print(function(args.input)) diff --git a/2019/aoc2019/day06.py b/2019/aoc2019/day06.py index f35a7aa..b06601b 100644 --- a/2019/aoc2019/day06.py +++ b/2019/aoc2019/day06.py @@ -1,6 +1,6 @@ from typing import TextIO -import networkx +import networkx # type: ignore def read_graph(data: TextIO) -> networkx.DiGraph: diff --git a/2019/aoc2019/day07.py b/2019/aoc2019/day07.py index b923273..ff24b5a 100644 --- a/2019/aoc2019/day07.py +++ b/2019/aoc2019/day07.py @@ -4,8 +4,8 @@ from typing import List, TextIO, Tuple from aoc2019.intcode import read_program, Computer -def amplify(phases: Tuple[int], program: List[int]) -> int: - amps = [] +def amplify(phases: Tuple[int, ...], program: List[int]) -> int: + amps: List[Computer] = [] for i, phase in enumerate(phases): amp = Computer(program.copy()) @@ -25,8 +25,8 @@ def amplify(phases: Tuple[int], program: List[int]) -> int: return amps[-1].output.pop() -def reamplify(phases: Tuple[int], program: List[int]) -> int: - amps = [] +def reamplify(phases: Tuple[int, ...], program: List[int]) -> int: + amps: List[Computer] = [] for i, _ in enumerate(phases): amp = Computer(program.copy()) diff --git a/2019/aoc2019/day08.py b/2019/aoc2019/day08.py new file mode 100644 index 0000000..8511313 --- /dev/null +++ b/2019/aoc2019/day08.py @@ -0,0 +1,33 @@ +from collections import Counter +from typing import Iterable, TextIO + +import numpy # type: ignore + + +def parse_layers(width: int, height: int, data: TextIO) -> Iterable[numpy.array]: + chunk_size = width * height + + content = next(data).strip() + + for pos in range(0, len(content), chunk_size): + yield numpy.array([int(c) for c in content[pos:pos + chunk_size]]) + + +def part1(data: TextIO) -> int: + best_layer: Counter[int] = min((Counter(layer) for layer in parse_layers(25, 6, data)), key=lambda c: c[0]) + + return best_layer[1] * best_layer[2] + + +def format_row(row: Iterable[int]) -> str: + return ''.join('#' if p == 1 else ' ' for p in row) + + +def part2(data: TextIO) -> str: + layers = list(parse_layers(25, 6, data)) + background = numpy.zeros(25 * 6, numpy.int8) + + for layer in reversed(layers): + background[layer != 2] = layer[layer != 2] + + return '\n'.join(format_row(row) for row in background.reshape(6, 25)) diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index 206fef4..406b28d 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -21,14 +21,11 @@ class Computer: self.output = collections.deque() def _mode_and_key(self, item: Union[int, Tuple[int, int]]) -> Tuple[int, int]: - if type(item) == int: - mode = 0 - key = item + if isinstance(item, int): + return 0, item else: mode, key = item - key = self.program[self.pointer + key] - - return mode, key + return mode, self.program[self.pointer + key] def __getitem__(self, item: Union[int, Tuple[int, int]]) -> int: mode, key = self._mode_and_key(item) diff --git a/2019/requirements.txt b/2019/requirements.txt index 5ff3949..3e5cfd1 100644 --- a/2019/requirements.txt +++ b/2019/requirements.txt @@ -1,2 +1,3 @@ pytest networkx +numpy From b65c805891560ae7f84c2411499b40d62c4eab08 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 24 Jan 2021 10:16:14 +0100 Subject: [PATCH 12/37] Implement 2019 day 9 --- 2019/aoc2019/day09.py | 25 +++++++++++++++++++++++++ 2019/aoc2019/intcode.py | 38 ++++++++++++++++++++++++++++---------- 2019/tests/test_intcode.py | 15 +++++++++++++++ 3 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 2019/aoc2019/day09.py diff --git a/2019/aoc2019/day09.py b/2019/aoc2019/day09.py new file mode 100644 index 0000000..8c483f5 --- /dev/null +++ b/2019/aoc2019/day09.py @@ -0,0 +1,25 @@ +import sys +from typing import TextIO + +from aoc2019.intcode import read_program, Computer + + +def run_machine(data: TextIO, initializer: int) -> int: + program = read_program(data) + computer = Computer(program) + computer.input.append(initializer) + + computer.run() + + if len(computer.output) > 1: + sys.exit(computer.output) + else: + return computer.output.pop() + + +def part1(data: TextIO) -> int: + return run_machine(data, 1) + + +def part2(data: TextIO) -> int: + return run_machine(data, 2) diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index 406b28d..d00801d 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -11,12 +11,14 @@ def read_program(data: TextIO) -> List[int]: class Computer: program: List[int] pointer: int + relative_base: int input: collections.deque[int] output: collections.deque[int] def __init__(self, program: List[int], pointer: int = 0) -> None: self.program = program self.pointer = pointer + self.relative_base = 0 self.input = collections.deque() self.output = collections.deque() @@ -30,29 +32,41 @@ class Computer: def __getitem__(self, item: Union[int, Tuple[int, int]]) -> int: mode, key = self._mode_and_key(item) - if mode == 0: - self._ensure_length(key + 1) - return self.program[key] - elif mode == 1: + if mode == 1: return key + elif mode == 0: + pass # Nothing to do here, handled below + elif mode == 2: + key += self.relative_base else: raise ValueError(f'Unsupported mode "{mode}"') + self._ensure_length(key + 1) + return self.program[key] + def __setitem__(self, item: Union[int, Tuple[int, int]], value: int) -> None: mode, key = self._mode_and_key(item) - if mode == 0: - self._ensure_length(key + 1) - self.program[key] = value - elif mode == 1: + if mode == 1: raise ValueError('Cannot assign to an immediate') + elif mode == 0: + pass # Nothing to do here, handled below + elif mode == 2: + key += self.relative_base else: raise ValueError(f'Unsupported mode "{mode}"') + self._ensure_length(key + 1) + self.program[key] = value + def _ensure_length(self, length: int) -> None: if len(self.program) < length: - # Double current program size with 0s - self.program.extend(0 for _ in range(len(self.program))) + if 2 * len(self.program) >= length: + # Double current program size with 0s + self.program.extend(0 for _ in range(len(self.program))) + else: + # Resize until the desired length + self.program.extend(0 for _ in range(length - len(self.program))) def run(self) -> None: """ Run until failure """ @@ -116,6 +130,10 @@ class Computer: else: self[mode[2], 3] = 0 self.pointer += 4 + elif opcode == 9: + # Adjust relative base + self.relative_base += self[mode[0], 1] + self.pointer += 2 elif opcode == 99: # Halt return False diff --git a/2019/tests/test_intcode.py b/2019/tests/test_intcode.py index ea4cbf5..b733951 100644 --- a/2019/tests/test_intcode.py +++ b/2019/tests/test_intcode.py @@ -64,3 +64,18 @@ def test_day5_example(inputs: int, expected: int): computer.run() assert computer.output.pop() == expected + + +@pytest.mark.parametrize('program,output', [ + ([109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99], + [109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99]), + ([1102, 34915192, 34915192, 7, 4, 7, 99, 0], [1219070632396864]), + ([104, 1125899906842624, 99], [1125899906842624]), +]) +def test_instructions_day9(program: List[int], output: List[int]) -> None: + computer = Computer(program) + computer.run() + + result = list(computer.output) + + assert result == output From 091c125f42463b372f0c2c99124578eb8fe13150 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 24 Jan 2021 10:22:37 +0100 Subject: [PATCH 13/37] Fix day 8 to paint front-to-back --- 2019/aoc2019/day08.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/2019/aoc2019/day08.py b/2019/aoc2019/day08.py index 8511313..0c1d818 100644 --- a/2019/aoc2019/day08.py +++ b/2019/aoc2019/day08.py @@ -24,10 +24,11 @@ def format_row(row: Iterable[int]) -> str: def part2(data: TextIO) -> str: - layers = list(parse_layers(25, 6, data)) background = numpy.zeros(25 * 6, numpy.int8) + background.fill(2) - for layer in reversed(layers): - background[layer != 2] = layer[layer != 2] + for layer in parse_layers(25, 6, data): + mask = background == 2 + background[mask] = layer[mask] return '\n'.join(format_row(row) for row in background.reshape(6, 25)) From 2907726363ba7c54df8738dabeb16c902efd17cc Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 24 Jan 2021 10:23:20 +0100 Subject: [PATCH 14/37] Don't build on Python Nightly Python nightly doesn't support Numpy, or the other way around, but either way it doesn't work and causes build failures. --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98e209c..2e0308f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,6 @@ language: python python: - "3.9" - - "nightly" - -jobs: - allow_failures: - - python: nightly - fast_finish: true # Custom directory, for the correct year before_install: From dd039e9276d3b4e00230856d1a2bd8266258c2f4 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 24 Jan 2021 13:54:48 +0100 Subject: [PATCH 15/37] Super messy 2019 day 10 I accidentally inverted my y-axis and I'm not fixing it. --- 2019/aoc2019/day10.py | 93 ++++++++++++++++++++++++++++++++++++++++ 2019/tests/test_day10.py | 86 +++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 2019/aoc2019/day10.py create mode 100644 2019/tests/test_day10.py diff --git a/2019/aoc2019/day10.py b/2019/aoc2019/day10.py new file mode 100644 index 0000000..f6ae006 --- /dev/null +++ b/2019/aoc2019/day10.py @@ -0,0 +1,93 @@ +import math +from collections import defaultdict +from typing import TextIO, Tuple + +import numpy # type: ignore + + +def read_asteroids(data: TextIO) -> Tuple[numpy.array, numpy.array]: + xs = [] + ys = [] + for y, line in enumerate(data): + for x, c in enumerate(line): + if c == '#': + xs.append(x) + ys.append(y) + + return numpy.array(xs), -numpy.array(ys) + + +def asteroids_visible(x: int, y: int, xs: numpy.array, ys: numpy.array) -> int: + dx = xs - x + dy = ys - y + + div = numpy.abs(numpy.gcd(dx, dy)) + + mask = div != 0 + + dx[mask] //= div[mask] + dy[mask] //= div[mask] + + unique = set(zip(dx, dy)) + + return len(unique) - 1 # need to ignore the point itself + + +def part1(data: TextIO) -> int: + xs, ys = read_asteroids(data) + + return max(asteroids_visible(x, y, xs, ys) for x, y in zip(xs, ys)) + + +def part2(data: TextIO) -> int: + xs, ys = read_asteroids(data) + + cx, cy = max(zip(xs, ys), key=lambda c: asteroids_visible(c[0], c[1], xs, ys)) + + dx = xs - cx + dy = ys - cy + + angles = numpy.arctan2(dy, dx) + distances = numpy.abs(numpy.copy(dx)) + numpy.abs(numpy.copy(dy)) + + to_shoot = defaultdict(list) + + for angle, distance, dx, dy in zip(angles, distances, dx, dy): + if distance == 0: + # The point itself + continue + + to_shoot[angle].append((distance, dx, dy)) + + for distances in to_shoot.values(): + distances.sort(reverse=True) + + unique_angles = sorted(set(angles), reverse=True) + + shot = 0 + + # First shoot from up clockwise + for angle in unique_angles: + if angle > math.pi / 2: + continue + + shot += 1 + + _, dx, dy = to_shoot[angle].pop() + + # Repeatedly shoot until you reach #200 + while True: + for angle in unique_angles: + if not to_shoot[angle]: + # Nothing left to shoot + continue + + shot += 1 + + _, dx, dy = to_shoot[angle].pop() + + if shot == 200: + x = cx + dx + y = -(cy + dy) + return 100 * x + y + diff --git a/2019/tests/test_day10.py b/2019/tests/test_day10.py new file mode 100644 index 0000000..9685a52 --- /dev/null +++ b/2019/tests/test_day10.py @@ -0,0 +1,86 @@ +from io import StringIO +from textwrap import dedent + +import pytest + +from aoc2019.day10 import part1, part2 + +LARGE_SAMPLE = """\ +.#..##.###...####### +##.############..##. +.#.######.########.# +.###.#######.####.#. +#####.##.#.##.###.## +..#####..#.######### +#################### +#.####....###.#.#.## +##.################# +#####.##.###..####.. +..######..##.####### +####.##.####...##..# +.#####..#.######.### +##...#.##########... +#.##########.####### +.####.#.###.###.#.## +....##.##.###..##### +.#.#.###########.### +#.#.#.#####.####.### +###.##.####.##.#..## +""" + + +@pytest.mark.parametrize('visible,field', [ + (8, dedent("""\ + .#..# + ..... + ##### + ....# + ...## + """)), + (33, dedent("""\ + ......#.#. + #..#.#.... + ..#######. + .#.#.###.. + .#..#..... + ..#....#.# + #..#....#. + .##.#..### + ##...#..#. + .#....#### + """)), + (35, dedent("""\ + #.#...#.#. + .###....#. + .#....#... + ##.#.#.#.# + ....#.#.#. + .##..###.# + ..#...##.. + ..##....## + ......#... + .####.###. + """)), + (41, dedent("""\ + .#..#..### + ####.###.# + ....###.#. + ..###.##.# + ##.##.#.#. + ....###..# + ..#.#..#.# + #..#.#.### + .##...##.# + .....#.#.. + """)), + (210, LARGE_SAMPLE), +]) +def test_samples_part1(visible: int, field: str) -> None: + data = StringIO(field.strip()) + assert part1(data) == visible + + +def test_samples_part2(): + data = StringIO(LARGE_SAMPLE.strip()) + + assert part2(data) == 802 From 2c767d59962d81af23c3165ab602c05e8db1e4b0 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 24 Jan 2021 17:35:42 +0100 Subject: [PATCH 16/37] Implement 2019 day 11 --- 2019/aoc2019/day10.py | 2 +- 2019/aoc2019/day11.py | 60 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 2019/aoc2019/day11.py diff --git a/2019/aoc2019/day10.py b/2019/aoc2019/day10.py index f6ae006..6fbb5f1 100644 --- a/2019/aoc2019/day10.py +++ b/2019/aoc2019/day10.py @@ -48,7 +48,7 @@ def part2(data: TextIO) -> int: dy = ys - cy angles = numpy.arctan2(dy, dx) - distances = numpy.abs(numpy.copy(dx)) + numpy.abs(numpy.copy(dy)) + distances = numpy.abs(dx) + numpy.abs(dy) to_shoot = defaultdict(list) diff --git a/2019/aoc2019/day11.py b/2019/aoc2019/day11.py new file mode 100644 index 0000000..79b95fb --- /dev/null +++ b/2019/aoc2019/day11.py @@ -0,0 +1,60 @@ +from typing import Dict, Optional, TextIO + +from aoc2019.intcode import Computer, read_program + + +def run_robot(data: TextIO, painted: Optional[Dict[complex, int]] = None) -> Dict[complex, int]: + if painted is None: + painted = {} + + computer = Computer(read_program(data)) + + pos = 0j + direction = 1j + + finished = False + + while not finished: + try: + computer.run() + finished = True + except IndexError: + pass + + while len(computer.output) >= 2: + paint = computer.output.popleft() + turn = computer.output.popleft() + + painted[pos] = paint + + if turn: + direction *= -1j + else: + direction *= 1j + + pos += direction + + computer.input.append(painted.get(pos, 0)) + + return painted + + +def part1(data: TextIO) -> int: + return len(run_robot(data)) + + +def part2(data: TextIO) -> str: + painted = run_robot(data, {0j: 1}) + + xmin = int(min(pos.real for pos in painted.keys())) + xmax = int(max(pos.real for pos in painted.keys())) + ymin = int(min(pos.imag for pos in painted.keys())) + ymax = int(max(pos.imag for pos in painted.keys())) + + image = '' + + for y in reversed(range(ymin, ymax + 1)): + line = ''.join('#' if painted.get(x + y * 1j) == 1 else ' ' for x in range(xmin, xmax + 1)) + image += f'{line}\n' + + return image[:-1] From f94661d7a8775d7a843d0ac2dcec5f61817ce83a Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 25 Jan 2021 20:55:39 +0100 Subject: [PATCH 17/37] Implement 2019 day 12 --- 2019/aoc2019/day12.py | 69 ++++++++++++++++++++++++++++++++++++++++ 2019/tests/test_day12.py | 25 +++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 2019/aoc2019/day12.py create mode 100644 2019/tests/test_day12.py diff --git a/2019/aoc2019/day12.py b/2019/aoc2019/day12.py new file mode 100644 index 0000000..6689711 --- /dev/null +++ b/2019/aoc2019/day12.py @@ -0,0 +1,69 @@ +import itertools +import math +import re +from typing import TextIO + +import numpy # type: ignore + + +def read_moons(data: TextIO) -> numpy.array: + moons = [] + + for line in data: + moon = [int(x) for x in re.split(r"[^-0-9]+", line) if x] + moons.append(moon) + + return numpy.array(moons) + + +def advance(pos: numpy.array, vel: numpy.array) -> None: + """ update pos and vel in place """ + pos_prime = numpy.repeat(numpy.reshape(pos, (1, len(pos))), len(pos), axis=0).transpose() - pos + pos_prime = -numpy.sign(pos_prime) + vel += numpy.sum(pos_prime, axis=1) + pos += vel + + +def simulate_moons(moons: numpy.array, iterations: int) -> int: + moons = numpy.transpose(moons) # Transpose so we have rows of x, y, z + velocity = numpy.zeros_like(moons) + + for _ in range(iterations): + for pos, vel in zip(moons, velocity): + advance(pos, vel) + + potential = numpy.sum(numpy.abs(moons), axis=0) + kinetic = numpy.sum(numpy.abs(velocity), axis=0) + + return int(numpy.sum(kinetic * potential)) + + +def find_repetition(moons: numpy.array) -> int: + moons = numpy.transpose(moons) + velocity = numpy.zeros_like(moons) + + needed = 1 + + for pos, vel in zip(moons, velocity): + pos_prime = numpy.copy(pos) + + for i in itertools.count(1): + advance(pos, vel) + + if (pos == pos_prime).all() and (vel == 0).all(): + needed *= i // math.gcd(needed, i) + break + + return needed + + +def part1(data: TextIO) -> int: + moons = read_moons(data) + + return simulate_moons(moons, 1000) + + +def part2(data: TextIO) -> int: + moons = read_moons(data) + + return find_repetition(moons) diff --git a/2019/tests/test_day12.py b/2019/tests/test_day12.py new file mode 100644 index 0000000..3441891 --- /dev/null +++ b/2019/tests/test_day12.py @@ -0,0 +1,25 @@ +import pytest +import numpy # type: ignore + +from aoc2019.day12 import simulate_moons, find_repetition + +SAMPLES = [ + numpy.array([[-1, 0, 2], [2, -10, -7], [4, -8, 8], [3, 5, -1]]), + numpy.array([[-8, -10, 0], [5, 5, 10], [2, -7, 3], [9, -8, -3]]), +] + + +@pytest.mark.parametrize('iterations,result,moons', [ + (10, 179, numpy.copy(SAMPLES[0])), + (100, 1940, numpy.copy(SAMPLES[1])), +]) +def test_kinetic_energy(moons: numpy.array, iterations: int, result: int) -> None: + assert simulate_moons(moons, iterations) == result + + +@pytest.mark.parametrize('outcome,moons', [ + (2772, numpy.copy(SAMPLES[0])), + (4686774924, numpy.copy(SAMPLES[1])), +]) +def test_repetition(moons: numpy.array, outcome: int) -> None: + assert find_repetition(moons) == outcome From c8c616dffcce4a8083e3415607b07da6ae1adc7a Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Fri, 29 Jan 2021 20:26:12 +0100 Subject: [PATCH 18/37] Implement 2019 day 13 part 1 --- 2019/aoc2019/day13.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 2019/aoc2019/day13.py diff --git a/2019/aoc2019/day13.py b/2019/aoc2019/day13.py new file mode 100644 index 0000000..c0d9a6d --- /dev/null +++ b/2019/aoc2019/day13.py @@ -0,0 +1,20 @@ +from typing import TextIO + +from aoc2019.intcode import Computer, read_program + + +def part1(data: TextIO) -> int: + computer = Computer(read_program(data)) + + computer.run() + + screen = {} + + while computer.output: + x = computer.output.popleft() + y = computer.output.popleft() + val = computer.output.popleft() + + screen[x, y] = val + + return sum(1 for val in screen.values() if val == 2) From c3671ec17770d431a374b373a4e2b055ee1e3809 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Fri, 29 Jan 2021 20:42:54 +0100 Subject: [PATCH 19/37] Implement 2019 day 13 part 2 --- 2019/aoc2019/day13.py | 53 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/2019/aoc2019/day13.py b/2019/aoc2019/day13.py index c0d9a6d..6e9337c 100644 --- a/2019/aoc2019/day13.py +++ b/2019/aoc2019/day13.py @@ -1,15 +1,10 @@ -from typing import TextIO +import statistics +from typing import TextIO, Tuple, Dict from aoc2019.intcode import Computer, read_program -def part1(data: TextIO) -> int: - computer = Computer(read_program(data)) - - computer.run() - - screen = {} - +def render_screen(computer: Computer, screen: Dict[Tuple[int, int], int]): while computer.output: x = computer.output.popleft() y = computer.output.popleft() @@ -17,4 +12,46 @@ def part1(data: TextIO) -> int: screen[x, y] = val + +def part1(data: TextIO) -> int: + computer = Computer(read_program(data)) + computer.run() + + screen = {} + + render_screen(computer, screen) + return sum(1 for val in screen.values() if val == 2) + + +def part2(data: TextIO) -> int: + computer = Computer(read_program(data)) + + computer.program[0] = 2 + + screen = {} + + finished = False + + while not finished: + try: + computer.run() + finished = True + except IndexError: + # Waiting for input + pass + + render_screen(computer, screen) + + ball_x = next(x for x, y in screen if screen[x, y] == 4) + + paddle_x = statistics.mean(x for x, y in screen if screen[x, y] == 3) + + if ball_x < paddle_x: + computer.input.append(-1) + elif ball_x > paddle_x: + computer.input.append(1) + else: + computer.input.append(0) + + return screen[-1, 0] From 43c063cef93fd42e63a7dc15b59388dccb9cbcc7 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 30 Jan 2021 10:08:16 +0100 Subject: [PATCH 20/37] Implement 2019 day 14 --- 2019/aoc2019/day14.py | 71 +++++++++++++++++++++++++++++++++++ 2019/tests/test_day14.py | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 2019/aoc2019/day14.py create mode 100644 2019/tests/test_day14.py diff --git a/2019/aoc2019/day14.py b/2019/aoc2019/day14.py new file mode 100644 index 0000000..f641ccd --- /dev/null +++ b/2019/aoc2019/day14.py @@ -0,0 +1,71 @@ +import math +from collections import defaultdict +from typing import TextIO, Tuple + +from networkx import DiGraph, topological_sort + + +def read_pair(item: str) -> Tuple[str, int]: + amount, element = item.split(' ') + + return element, int(amount) + + +def read_recipes(data: TextIO) -> DiGraph: + graph = DiGraph() + + for line in data: + requisites, production = line.strip().split(' => ') + + produced, produced_amount = read_pair(production) + graph.add_node(produced, weight=produced_amount) + + for requisite in requisites.split(', '): + required, required_amount = read_pair(requisite) + graph.add_edge(produced, required, weight=required_amount) + + return graph + + +def ore_required(graph: DiGraph, fuel_required: int) -> int: + requirements = defaultdict(int) + requirements['FUEL'] = fuel_required + + for element in topological_sort(graph): + if element not in requirements: + continue + + if element == 'ORE': + break + + element_produced = graph.nodes[element]['weight'] + productions_required = math.ceil(requirements[element] / element_produced) + + for _, elem_required, amount_required in graph.edges(element, data='weight'): + requirements[elem_required] += amount_required * productions_required + + return requirements['ORE'] + + +def part1(data: TextIO) -> int: + return ore_required(read_recipes(data), 1) + + +def part2(data: TextIO) -> int: + ore_available = 1000000000000 + graph = read_recipes(data) + + min_possible = 1 # lower bound of ORE / ore_required(graph, 1) exists but is slower + max_possible = ore_available + + while min_possible != max_possible: + check = min_possible + (max_possible - min_possible + 1) // 2 + + required = ore_required(graph, check) + + if required <= ore_available: + min_possible = check + else: + max_possible = check - 1 + + return min_possible diff --git a/2019/tests/test_day14.py b/2019/tests/test_day14.py new file mode 100644 index 0000000..41e9a5a --- /dev/null +++ b/2019/tests/test_day14.py @@ -0,0 +1,80 @@ +from io import StringIO +from textwrap import dedent + +import pytest + +from aoc2019.day14 import part1, part2 + +SAMPLES = [ + dedent("""\ + 9 ORE => 2 A + 8 ORE => 3 B + 7 ORE => 5 C + 3 A, 4 B => 1 AB + 5 B, 7 C => 1 BC + 4 C, 1 A => 1 CA + 2 AB, 3 BC, 4 CA => 1 FUEL + """), + dedent("""\ + 157 ORE => 5 NZVS + 165 ORE => 6 DCFZ + 44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL + 12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ + 179 ORE => 7 PSHF + 177 ORE => 5 HKGWZ + 7 DCFZ, 7 PSHF => 2 XJWVT + 165 ORE => 2 GPVTF + 3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT + """), + dedent("""\ + 2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG + 17 NVRVD, 3 JNWZP => 8 VPVL + 53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL + 22 VJHF, 37 MNCFX => 5 FWMGM + 139 ORE => 4 NVRVD + 144 ORE => 7 JNWZP + 5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC + 5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV + 145 ORE => 6 MNCFX + 1 NVRVD => 8 CXFTF + 1 VJHF, 6 MNCFX => 4 RFSQX + 176 ORE => 6 VJHF + """), + dedent("""\ + 171 ORE => 8 CNZTR + 7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL + 114 ORE => 4 BHXH + 14 VRPVC => 6 BMBT + 6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL + 6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT + 15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW + 13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW + 5 BMBT => 4 WPTQ + 189 ORE => 9 KTJDG + 1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP + 12 VRPVC, 27 CNZTR => 2 XDBXC + 15 KTJDG, 12 BHXH => 5 XCVML + 3 BHXH, 2 VRPVC => 7 MZWV + 121 ORE => 7 VRPVC + 7 XCVML => 6 RJRHP + 5 BHXH, 4 VRPVC => 5 LTCX + """), +] + + +@pytest.mark.parametrize("sample,correct", zip(SAMPLES, [165, 13312, 180697, 2210736])) +def test_part1(sample: str, correct: int): + data = StringIO(sample) + + result = part1(data) + + assert result == correct + + +@pytest.mark.parametrize("sample,correct", zip(SAMPLES[1:], [82892753, 5586022, 460664])) +def test_part2(sample: str, correct: int): + data = StringIO(sample) + + result = part2(data) + + assert result == correct From eff22abf8a194c465ac4b4c996d678696b87f2c2 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 30 Jan 2021 10:09:19 +0100 Subject: [PATCH 21/37] Fix mypy issues --- 2019/aoc2019/day13.py | 4 ++-- 2019/aoc2019/day14.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/2019/aoc2019/day13.py b/2019/aoc2019/day13.py index 6e9337c..5aea8bd 100644 --- a/2019/aoc2019/day13.py +++ b/2019/aoc2019/day13.py @@ -17,7 +17,7 @@ def part1(data: TextIO) -> int: computer = Computer(read_program(data)) computer.run() - screen = {} + screen: Dict[Tuple[int, int], int] = {} render_screen(computer, screen) @@ -29,7 +29,7 @@ def part2(data: TextIO) -> int: computer.program[0] = 2 - screen = {} + screen: Dict[Tuple[int, int], int] = {} finished = False diff --git a/2019/aoc2019/day14.py b/2019/aoc2019/day14.py index f641ccd..2530837 100644 --- a/2019/aoc2019/day14.py +++ b/2019/aoc2019/day14.py @@ -2,7 +2,7 @@ import math from collections import defaultdict from typing import TextIO, Tuple -from networkx import DiGraph, topological_sort +from networkx import DiGraph, topological_sort # type: ignore[import] def read_pair(item: str) -> Tuple[str, int]: From 165159cba946591a91f1835bd0cd96c34e23b62f Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 1 Feb 2021 22:39:09 +0100 Subject: [PATCH 22/37] Implement 2019 day 15 --- 2019/aoc2019/day15.py | 102 ++++++++++++++++++++++++++++++++++++++++ 2019/aoc2019/intcode.py | 3 ++ 2 files changed, 105 insertions(+) create mode 100644 2019/aoc2019/day15.py diff --git a/2019/aoc2019/day15.py b/2019/aoc2019/day15.py new file mode 100644 index 0000000..2373d25 --- /dev/null +++ b/2019/aoc2019/day15.py @@ -0,0 +1,102 @@ +import sys +from collections import defaultdict +from typing import TextIO + +import networkx # type: ignore + +from aoc2019.intcode import Computer, read_program + + +def step(computer: Computer, direction: int) -> int: + computer.input.append(direction) + + try: + computer.run() + except IndexError: + return computer.get_output() + + sys.exit("computer terminated unexpectedly") + + +def inverse(direction: int): + if direction % 2 == 1: + return direction + 1 + else: + return direction - 1 + + +def read_graph(data: TextIO) -> networkx.Graph: + computer = Computer(read_program(data)) + + pos = (0, 0) + tiles = defaultdict(int) + tiles[0, 0] = 1 + + prev = [((0, 0), 1)] + + while prev: + x, y = pos + + if (x, y + 1) not in tiles: + movement = 1 + next_pos = (x, y + 1) + elif (x, y - 1) not in tiles: + movement = 2 + next_pos = (x, y - 1) + elif (x - 1, y) not in tiles: + movement = 3 + next_pos = (x - 1, y) + elif (x + 1, y) not in tiles: + movement = 4 + next_pos = (x + 1, y) + else: + # No movement available, backtrack + prev_pos, prev_dir = prev.pop() + step(computer, inverse(prev_dir)) + pos = prev_pos + continue + + result = step(computer, movement) + tiles[next_pos] = result + + if result != 0: + # Movement was successful + prev.append((pos, movement)) + pos = next_pos + + graph = networkx.Graph() + + for pos, value in tiles.items(): + if value == 0: + continue + + if value == 2: + # Create an imaginary edge to the oxygen + graph.add_edge('O', pos, weight=0) + + x, y = pos + + neighbours = [ + (x - 1, y), + (x + 1, y), + (x, y - 1), + (x, y + 1), + ] + + for neighbour in neighbours: + if tiles[neighbour] != 0: + graph.add_edge(pos, neighbour) + + return graph + + +def part1(data: TextIO) -> int: + graph = read_graph(data) + + return networkx.shortest_path_length(graph, (0, 0), 'O') - 1 + + +def part2(data: TextIO) -> int: + graph = read_graph(data) + + return networkx.eccentricity(graph, 'O') - 1 diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index d00801d..d90fac9 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -73,6 +73,9 @@ class Computer: while self._execute_current(): pass + def get_output(self) -> int: + return self.output.popleft() + def _execute_current(self) -> bool: """ Execute a single instruction From 2d561eab7d534f2b597f560d796e04dbc82b0ca6 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Tue, 2 Feb 2021 19:12:10 +0100 Subject: [PATCH 23/37] Implement 2019 day 16 part 1 --- 2019/aoc2019/day16.py | 33 +++++++++++++++++++++++++++++++++ 2019/tests/day16.py | 15 +++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 2019/aoc2019/day16.py create mode 100644 2019/tests/day16.py diff --git a/2019/aoc2019/day16.py b/2019/aoc2019/day16.py new file mode 100644 index 0000000..217fe68 --- /dev/null +++ b/2019/aoc2019/day16.py @@ -0,0 +1,33 @@ +import math +from typing import List, TextIO + +import numpy # type: ignore + + +def read_input(data: TextIO) -> List[int]: + line = next(data).strip() + + return [int(c) for c in line] + + +def simulate(numbers: List[int]) -> str: + numbers = numpy.array(numbers) + pattern = numpy.array([0, 1, 0, -1], dtype=numpy.int) + + matrix = numpy.zeros((len(numbers), len(numbers)), dtype=numpy.int) + + for i in range(len(numbers)): + base = numpy.repeat(pattern, i + 1) + needed_repetitions = math.ceil((len(numbers) + 1) / len(base)) + matrix[i, :] = numpy.tile(base, needed_repetitions)[1:len(numbers) + 1] + + for _ in range(100): + numbers = numpy.abs(numpy.dot(matrix, numbers)) % 10 + + return ''.join(str(s) for s in numbers[:8]) + + +def part1(data: TextIO) -> str: + numbers = read_input(data) + + return simulate(numbers) diff --git a/2019/tests/day16.py b/2019/tests/day16.py new file mode 100644 index 0000000..f83024d --- /dev/null +++ b/2019/tests/day16.py @@ -0,0 +1,15 @@ +import pytest + +from aoc2019.day16 import simulate + + +@pytest.mark.parametrize('data,correct', [ + ('80871224585914546619083218645595', '24176176'), + ('19617804207202209144916044189917', '73745418'), + ('69317163492948606335995924319873', '52432133'), +]) +def test_sample_part1(data: str, correct: str): + numbers = [int(c) for c in data] + + assert simulate(numbers) == correct + pass From beae045f5518afaf6e71e822fddbdc1840dbcb4e Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Tue, 2 Feb 2021 19:57:24 +0100 Subject: [PATCH 24/37] Implement 2019 day 16 part 2 --- 2019/aoc2019/day16.py | 24 ++++++++++++++++++++++++ 2019/tests/day16.py | 15 --------------- 2019/tests/test_day16.py | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 15 deletions(-) delete mode 100644 2019/tests/day16.py create mode 100644 2019/tests/test_day16.py diff --git a/2019/aoc2019/day16.py b/2019/aoc2019/day16.py index 217fe68..e61987e 100644 --- a/2019/aoc2019/day16.py +++ b/2019/aoc2019/day16.py @@ -27,7 +27,31 @@ def simulate(numbers: List[int]) -> str: return ''.join(str(s) for s in numbers[:8]) +def simulate2(numbers: List[int]) -> str: + numbers = numpy.tile(numpy.array(numbers, dtype=numpy.int), 10000) + starting_index = 0 + + for n in numbers[:7]: + starting_index *= 10 + starting_index += n + + assert starting_index > len(numbers) / 2 + + numbers = numbers[starting_index:] + + for _ in range(100): + numbers = numpy.abs(numpy.flip(numpy.cumsum(numpy.flip(numbers)))) % 10 + + return ''.join(str(s) for s in numbers[:8]) + + def part1(data: TextIO) -> str: numbers = read_input(data) return simulate(numbers) + + +def part2(data: TextIO) -> str: + numbers = read_input(data) + + return simulate2(numbers) diff --git a/2019/tests/day16.py b/2019/tests/day16.py deleted file mode 100644 index f83024d..0000000 --- a/2019/tests/day16.py +++ /dev/null @@ -1,15 +0,0 @@ -import pytest - -from aoc2019.day16 import simulate - - -@pytest.mark.parametrize('data,correct', [ - ('80871224585914546619083218645595', '24176176'), - ('19617804207202209144916044189917', '73745418'), - ('69317163492948606335995924319873', '52432133'), -]) -def test_sample_part1(data: str, correct: str): - numbers = [int(c) for c in data] - - assert simulate(numbers) == correct - pass diff --git a/2019/tests/test_day16.py b/2019/tests/test_day16.py new file mode 100644 index 0000000..67a49db --- /dev/null +++ b/2019/tests/test_day16.py @@ -0,0 +1,25 @@ +import pytest + +from aoc2019.day16 import simulate, simulate2 + + +@pytest.mark.parametrize('data,correct', [ + ('80871224585914546619083218645595', '24176176'), + ('19617804207202209144916044189917', '73745418'), + ('69317163492948606335995924319873', '52432133'), +]) +def test_sample_part1(data: str, correct: str): + numbers = [int(c) for c in data] + + assert simulate(numbers) == correct + + +@pytest.mark.parametrize('data,correct', [ + ('03036732577212944063491565474664', '84462026'), + ('02935109699940807407585447034323', '78725270'), + ('03081770884921959731165446850517', '53553731'), +]) +def test_sample_part2(data: str, correct: str): + numbers = [int(c) for c in data] + + assert simulate2(numbers) == correct From a43f260e1be3da45c9acaa73c715888ab3350714 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Tue, 9 Feb 2021 20:20:17 +0100 Subject: [PATCH 25/37] Implement day 17 part 1 --- 2019/aoc2019/day17.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 2019/aoc2019/day17.py diff --git a/2019/aoc2019/day17.py b/2019/aoc2019/day17.py new file mode 100644 index 0000000..7c5cdde --- /dev/null +++ b/2019/aoc2019/day17.py @@ -0,0 +1,26 @@ +from typing import TextIO + +from aoc2019.intcode import Computer, read_program + + +def part1(data: TextIO) -> int: + computer = Computer(read_program(data)) + + computer.run() + + output = ''.join(chr(c) for c in computer.output) + + tiles = set() + + for y, line in enumerate(output.splitlines()): + for x, c in enumerate(line): + if c == '#': + tiles.add((x, y)) + + total = 0 + + for x, y in tiles: + if (x - 1, y) in tiles and (x + 1, y) in tiles and (x, y - 1) in tiles and (x, y + 1) in tiles: + total += x * y + + return total From abc742e2ad8fc53b7ef5166ae0a41a89458966e9 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 14:15:11 +0200 Subject: [PATCH 26/37] Implement day 22 part 1 --- 2019/aoc2019/day22.py | 44 ++++++++++++++++++++++++++++++++++++++++ 2019/tests/test_day22.py | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 2019/aoc2019/day22.py create mode 100644 2019/tests/test_day22.py diff --git a/2019/aoc2019/day22.py b/2019/aoc2019/day22.py new file mode 100644 index 0000000..fc54e39 --- /dev/null +++ b/2019/aoc2019/day22.py @@ -0,0 +1,44 @@ +from typing import List, TextIO + + +def shuffle(instructions: List[str], deck_size: int) -> List[int]: + deck = list(range(0, deck_size)) + + for instruction in instructions: + if "new stack" in instruction: + deck = list(reversed(deck)) + continue + + parts = instruction.split(" ") + if parts[0] == "cut": + by = int(parts[1]) + + new_deck = deck[by:] + new_deck += deck[:by] + + deck = new_deck + else: + increment = int(parts[3]) + + new_deck = list(range(0, deck_size)) + target_index = 0 + + for card in deck: + new_deck[target_index] = card + target_index = (target_index + increment) % len(deck) + + deck = new_deck + + return deck + + +def part1(data: TextIO): + instructions = [line.strip() for line in data] + + result = shuffle(instructions, 10007) + + for i, card in enumerate(result): + if card == 2019: + return i + + raise Exception("Did not find card") diff --git a/2019/tests/test_day22.py b/2019/tests/test_day22.py new file mode 100644 index 0000000..78866a7 --- /dev/null +++ b/2019/tests/test_day22.py @@ -0,0 +1,43 @@ +import pytest + +from aoc2019.day22 import shuffle + +SAMPLE_INSTRUCTIONS = [ + """deal with increment 7 + deal into new stack + deal into new stack""", + """cut 6 + deal with increment 7 + deal into new stack""", + """deal with increment 7 + deal with increment 9 + cut -2""", + """deal into new stack + cut -2 + deal with increment 7 + cut 8 + cut -4 + deal with increment 7 + cut 3 + deal with increment 9 + deal with increment 3 + cut -1""", +] + +CORRECT_SHUFFLES = [ + "0 3 6 9 2 5 8 1 4 7", + "3 0 7 4 1 8 5 2 9 6", + "6 3 0 7 4 1 8 5 2 9", + "9 2 5 8 1 4 7 0 3 6", +] + + +@pytest.mark.parametrize('instructions,correct', zip(SAMPLE_INSTRUCTIONS, CORRECT_SHUFFLES)) +def test_shuffle(instructions, correct): + instructions = [line.strip() for line in instructions.splitlines()] + + correct = [int(i) for i in correct.split(" ")] + + result = shuffle(instructions, 10) + + assert result == correct From 22091fc8c360a8ddffacb122e5c7d2c5fd50ae94 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 15:05:49 +0200 Subject: [PATCH 27/37] Implement day 22 part 2 --- 2019/aoc2019/day22.py | 48 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/2019/aoc2019/day22.py b/2019/aoc2019/day22.py index fc54e39..e3cdfb4 100644 --- a/2019/aoc2019/day22.py +++ b/2019/aoc2019/day22.py @@ -32,7 +32,7 @@ def shuffle(instructions: List[str], deck_size: int) -> List[int]: return deck -def part1(data: TextIO): +def part1(data: TextIO) -> int: instructions = [line.strip() for line in data] result = shuffle(instructions, 10007) @@ -42,3 +42,49 @@ def part1(data: TextIO): return i raise Exception("Did not find card") + + +def modpow(a: int, b: int, m: int) -> int: + assert b >= 0 + + result = 1 + n = a + + while b > 0: + if b % 2: + result = (result * n) % m + + b //= 2 + n = (n * n) % m + + return result + + +def inverse(a: int, m: int) -> int: + """ Computes the modulo multiplicative inverse """ + return modpow(a, m - 2, m) + + +def part2(data: TextIO) -> int: + deck_size = 119315717514047 + shuffles = 101741582076661 + + a, b = 1, 0 + + for line in data: + parts = line.split(' ') + if 'new stack' in line: + la, lb = -1, -1 + elif parts[0] == 'deal': + la, lb = int(parts[-1]), 0 + else: + la, lb = 1, -int(parts[-1]) + + a = (la * a) % deck_size + b = (la * b + lb) % deck_size + + final_a = modpow(a, shuffles, deck_size) + final_b = ((b * (final_a - 1)) * inverse(a - 1, deck_size)) % deck_size + + return ((2020 - final_b) * inverse(final_a, deck_size)) % deck_size + From befa2eefaa3245852680a1d12a473d0d91476d42 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 15:19:13 +0200 Subject: [PATCH 28/37] Replace Travis with Github Actions --- .github/workflows/2019.yml | 18 ++++++++++++++++++ .travis.yml | 18 ------------------ 2 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/2019.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/2019.yml b/.github/workflows/2019.yml new file mode 100644 index 0000000..bcdb82b --- /dev/null +++ b/.github/workflows/2019.yml @@ -0,0 +1,18 @@ +name: AOC 2019 test suite +on: + push: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r 2019/requirements.txt + - name: Run Pytest + run: pytest 2019 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2e0308f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -dist: bionic -language: python - -python: - - "3.9" - -# Custom directory, for the correct year -before_install: - - cd 2019 - - python -m pip install --upgrade pip - -script: pytest - -cache: - directories: - - $HOME/.cache/pip -before_cache: - - rm -f $HOME/.cache/pip/log/debug.log From 3f8c9505c3363a1bc439d40852cdeabcb6f1af27 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 15:26:38 +0200 Subject: [PATCH 29/37] Fix numpy deprecation --- 2019/aoc2019/day16.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/2019/aoc2019/day16.py b/2019/aoc2019/day16.py index e61987e..d77482d 100644 --- a/2019/aoc2019/day16.py +++ b/2019/aoc2019/day16.py @@ -12,9 +12,9 @@ def read_input(data: TextIO) -> List[int]: def simulate(numbers: List[int]) -> str: numbers = numpy.array(numbers) - pattern = numpy.array([0, 1, 0, -1], dtype=numpy.int) + pattern = numpy.array([0, 1, 0, -1], dtype=numpy.int32) - matrix = numpy.zeros((len(numbers), len(numbers)), dtype=numpy.int) + matrix = numpy.zeros((len(numbers), len(numbers)), dtype=numpy.int32) for i in range(len(numbers)): base = numpy.repeat(pattern, i + 1) @@ -28,7 +28,7 @@ def simulate(numbers: List[int]) -> str: def simulate2(numbers: List[int]) -> str: - numbers = numpy.tile(numpy.array(numbers, dtype=numpy.int), 10000) + numbers = numpy.tile(numpy.array(numbers, dtype=numpy.int32), 10000) starting_index = 0 for n in numbers[:7]: From ca43475a44c26102c97bf693aedfce6b322c424d Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 17:57:40 +0200 Subject: [PATCH 30/37] Implement day 23 --- 2019/aoc2019/day23.py | 78 +++++++++++++++++++++++++++++++++++++++++ 2019/aoc2019/intcode.py | 3 ++ 2 files changed, 81 insertions(+) create mode 100644 2019/aoc2019/day23.py diff --git a/2019/aoc2019/day23.py b/2019/aoc2019/day23.py new file mode 100644 index 0000000..989a165 --- /dev/null +++ b/2019/aoc2019/day23.py @@ -0,0 +1,78 @@ +from typing import TextIO + +from aoc2019.intcode import read_program, Computer + + +def part1(data: TextIO) -> int: + program = read_program(data) + + computers = [Computer(program.copy()) for _ in range(50)] + + for i, computer in enumerate(computers): + computer.send_input(i) + + while True: + for computer in computers: + try: + computer.run() + except IndexError: + computer.send_input(-1) + + while len(computer.output) >= 3: + dest = computer.get_output() + x = computer.get_output() + y = computer.get_output() + + if dest == 255: + return y + + computers[dest].send_input(x) + computers[dest].send_input(y) + + +def part2(data: TextIO) -> int: + program = read_program(data) + + computers = [Computer(program.copy()) for _ in range(50)] + + for i, computer in enumerate(computers): + computer.send_input(i) + + nat_value = None + last_sent = None + + while True: + is_idle = True + + for computer in computers: + try: + computer._execute_current() + is_idle = False + except IndexError: + computer.send_input(-1) + + try: + computer.run() + except IndexError: + pass + + while len(computer.output) >= 3: + dest = computer.get_output() + x = computer.get_output() + y = computer.get_output() + + if dest == 255: + nat_value = (x, y) + else: + computers[dest].send_input(x) + computers[dest].send_input(y) + + if is_idle: + x, y = nat_value + + if last_sent == nat_value: + return y + else: + computers[0].send_input(x) + computers[0].send_input(y) + last_sent = nat_value diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index d90fac9..6b060a1 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -76,6 +76,9 @@ class Computer: def get_output(self) -> int: return self.output.popleft() + def send_input(self, data: int): + self.input.append(data) + def _execute_current(self) -> bool: """ Execute a single instruction From 05e2a4f3a77c6e140890588d5e7fa3a06d19c49d Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 17:59:43 +0200 Subject: [PATCH 31/37] intcode: make execute current not protected --- 2019/aoc2019/day23.py | 2 +- 2019/aoc2019/intcode.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/2019/aoc2019/day23.py b/2019/aoc2019/day23.py index 989a165..e1c6aff 100644 --- a/2019/aoc2019/day23.py +++ b/2019/aoc2019/day23.py @@ -46,7 +46,7 @@ def part2(data: TextIO) -> int: for computer in computers: try: - computer._execute_current() + computer.execute_current() is_idle = False except IndexError: computer.send_input(-1) diff --git a/2019/aoc2019/intcode.py b/2019/aoc2019/intcode.py index 6b060a1..86777a3 100644 --- a/2019/aoc2019/intcode.py +++ b/2019/aoc2019/intcode.py @@ -70,7 +70,7 @@ class Computer: def run(self) -> None: """ Run until failure """ - while self._execute_current(): + while self.execute_current(): pass def get_output(self) -> int: @@ -79,7 +79,7 @@ class Computer: def send_input(self, data: int): self.input.append(data) - def _execute_current(self) -> bool: + def execute_current(self) -> bool: """ Execute a single instruction :return: True if the program should continue From dbf6b2eb1707c6b4a4784f36fd446fb9d8f2808c Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 3 Jul 2021 17:59:58 +0200 Subject: [PATCH 32/37] Add input day 23 --- 2019/inputs/23.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 2019/inputs/23.txt diff --git a/2019/inputs/23.txt b/2019/inputs/23.txt new file mode 100644 index 0000000..ab9ab47 --- /dev/null +++ b/2019/inputs/23.txt @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2251,105,1,0,1544,1754,1952,705,2088,571,1120,1388,1921,1223,798,1025,1723,1688,2018,1153,1851,1355,1616,1585,1192,1091,1820,670,1890,2218,2121,1058,829,862,1985,1322,1785,736,767,984,637,2152,1653,953,1254,922,2187,1289,1423,2055,1493,893,1454,600,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1106,0,73,3,65,20102,1,64,1,21001,66,0,2,21102,105,1,0,1106,0,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,132,1,132,68,132,1001,0,0,62,1001,132,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,1,0,0,1001,161,1,169,102,1,65,0,1102,1,1,61,1102,0,1,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1105,1,178,21102,210,1,0,105,1,69,1201,1,0,70,1102,0,1,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1106,0,218,1105,1,73,109,4,21102,1,0,-3,21101,0,0,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1106,0,263,21201,-3,0,-3,109,-4,2105,1,0,109,4,21102,1,1,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,21202,-3,1,-3,109,-4,2106,0,0,109,1,101,1,68,359,20101,0,0,1,101,3,68,366,21001,0,0,2,21101,376,0,0,1106,0,436,22102,1,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21101,0,0,-4,21101,0,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,385,471,20102,1,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1105,1,547,21102,1,-1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1105,1,529,22101,0,-4,-7,109,-8,2105,1,0,109,1,101,1,68,564,20101,0,0,0,109,-1,2106,0,0,1102,1,53051,66,1102,1,1,67,1102,1,598,68,1101,0,556,69,1102,1,0,71,1102,600,1,72,1105,1,73,1,1722,1101,0,5077,66,1102,1,4,67,1102,627,1,68,1101,0,302,69,1101,1,0,71,1101,0,635,72,1105,1,73,0,0,0,0,0,0,0,0,35,174302,1102,47779,1,66,1101,0,2,67,1102,1,664,68,1101,0,302,69,1101,1,0,71,1102,1,668,72,1106,0,73,0,0,0,0,16,39722,1101,0,85669,66,1101,3,0,67,1101,0,697,68,1101,302,0,69,1102,1,1,71,1101,703,0,72,1105,1,73,0,0,0,0,0,0,16,79444,1101,0,12791,66,1101,0,1,67,1102,1,732,68,1101,556,0,69,1101,1,0,71,1101,0,734,72,1106,0,73,1,12,32,39367,1102,9067,1,66,1101,1,0,67,1101,0,763,68,1101,556,0,69,1101,0,1,71,1101,0,765,72,1106,0,73,1,-9965,16,59583,1102,77999,1,66,1102,1,1,67,1101,0,794,68,1101,0,556,69,1101,1,0,71,1101,0,796,72,1105,1,73,1,-83,23,85669,1101,2663,0,66,1101,0,1,67,1102,825,1,68,1101,0,556,69,1101,0,1,71,1102,827,1,72,1105,1,73,1,-12653,6,23053,1102,1,2659,66,1101,2,0,67,1102,856,1,68,1102,302,1,69,1101,0,1,71,1102,1,860,72,1106,0,73,0,0,0,0,18,209697,1101,0,1579,66,1101,0,1,67,1102,1,889,68,1101,0,556,69,1102,1,1,71,1101,891,0,72,1105,1,73,1,23,14,17571,1101,0,98467,66,1101,1,0,67,1101,920,0,68,1102,556,1,69,1101,0,0,71,1101,922,0,72,1105,1,73,1,1270,1102,6599,1,66,1101,0,1,67,1102,949,1,68,1101,0,556,69,1101,1,0,71,1101,951,0,72,1105,1,73,1,421,23,171338,1102,1,84857,66,1102,1,1,67,1101,980,0,68,1102,1,556,69,1102,1,1,71,1102,982,1,72,1106,0,73,1,55931,31,49363,1102,87151,1,66,1101,6,0,67,1102,1011,1,68,1101,302,0,69,1102,1,1,71,1101,1023,0,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,30,185798,1101,0,44893,66,1102,1,2,67,1101,0,1052,68,1101,302,0,69,1102,1,1,71,1102,1,1056,72,1105,1,73,0,0,0,0,48,426815,1102,1,89681,66,1102,1,1,67,1102,1,1085,68,1102,556,1,69,1101,2,0,71,1102,1087,1,72,1106,0,73,1,10,49,10154,35,348604,1101,42157,0,66,1102,1,1,67,1101,0,1118,68,1101,556,0,69,1102,1,0,71,1101,0,1120,72,1105,1,73,1,1351,1101,23053,0,66,1101,0,2,67,1102,1,1147,68,1101,302,0,69,1102,1,1,71,1102,1151,1,72,1105,1,73,0,0,0,0,36,47779,1102,24967,1,66,1102,1,5,67,1101,0,1180,68,1101,0,302,69,1101,0,1,71,1102,1190,1,72,1105,1,73,0,0,0,0,0,0,0,0,0,0,18,69899,1101,0,19163,66,1102,1,1,67,1102,1,1219,68,1102,556,1,69,1101,0,1,71,1102,1221,1,72,1106,0,73,1,32,45,7879,1101,0,82267,66,1101,0,1,67,1101,1250,0,68,1101,556,0,69,1102,1,1,71,1101,1252,0,72,1105,1,73,1,-2,15,124835,1102,71569,1,66,1101,3,0,67,1102,1281,1,68,1101,302,0,69,1101,0,1,71,1101,0,1287,72,1105,1,73,0,0,0,0,0,0,38,180398,1101,0,34361,66,1102,2,1,67,1102,1316,1,68,1102,1,302,69,1102,1,1,71,1102,1,1320,72,1106,0,73,0,0,0,0,32,78734,1102,1,49363,66,1102,2,1,67,1101,0,1349,68,1101,0,302,69,1102,1,1,71,1102,1,1353,72,1105,1,73,0,0,0,0,25,1198,1102,101293,1,66,1102,1,1,67,1102,1,1382,68,1101,556,0,69,1102,1,2,71,1101,1384,0,72,1106,0,73,1,439,15,99868,40,71569,1101,0,33769,66,1102,1,1,67,1102,1415,1,68,1102,556,1,69,1102,3,1,71,1102,1417,1,72,1106,0,73,1,5,49,5077,49,20308,35,87151,1101,0,38651,66,1102,1,1,67,1101,0,1450,68,1102,556,1,69,1101,1,0,71,1101,1452,0,72,1106,0,73,1,16763,43,68722,1102,85363,1,66,1101,0,5,67,1102,1481,1,68,1102,1,302,69,1102,1,1,71,1101,0,1491,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,28,5318,1101,0,8969,66,1101,1,0,67,1101,0,1520,68,1102,1,556,69,1102,11,1,71,1102,1,1522,72,1105,1,73,1,1,23,257007,6,46106,36,95558,14,5857,43,34361,32,118101,31,98726,25,599,4,105722,11,89786,40,143138,1102,1,68891,66,1101,1,0,67,1102,1571,1,68,1101,556,0,69,1102,1,6,71,1102,1,1573,72,1106,0,73,1,25970,28,2659,38,90199,38,270597,13,5659,13,11318,13,16977,1102,23593,1,66,1102,1,1,67,1102,1612,1,68,1101,556,0,69,1102,1,1,71,1101,1614,0,72,1106,0,73,1,37,15,74901,1102,1,69899,66,1102,4,1,67,1102,1643,1,68,1101,253,0,69,1102,1,1,71,1102,1651,1,72,1106,0,73,0,0,0,0,0,0,0,0,30,92899,1101,0,90199,66,1102,3,1,67,1102,1,1680,68,1101,302,0,69,1102,1,1,71,1102,1686,1,72,1105,1,73,0,0,0,0,0,0,18,139798,1102,5659,1,66,1102,1,3,67,1102,1,1715,68,1101,302,0,69,1102,1,1,71,1102,1721,1,72,1105,1,73,0,0,0,0,0,0,18,279596,1102,51551,1,66,1101,1,0,67,1101,0,1750,68,1101,0,556,69,1101,1,0,71,1102,1,1752,72,1106,0,73,1,-132,40,214707,1102,1,44269,66,1102,1,1,67,1102,1781,1,68,1101,0,556,69,1102,1,1,71,1102,1,1783,72,1106,0,73,1,8,48,341452,1101,39367,0,66,1101,0,3,67,1102,1,1812,68,1102,1,302,69,1102,1,1,71,1101,0,1818,72,1106,0,73,0,0,0,0,0,0,16,99305,1101,88471,0,66,1101,0,1,67,1102,1,1847,68,1102,556,1,69,1102,1,1,71,1101,1849,0,72,1105,1,73,1,-46,14,11714,1101,0,19861,66,1101,5,0,67,1101,0,1878,68,1102,1,253,69,1102,1,1,71,1101,1888,0,72,1105,1,73,0,0,0,0,0,0,0,0,0,0,45,15758,1102,3889,1,66,1102,1,1,67,1102,1,1917,68,1101,556,0,69,1102,1,1,71,1102,1,1919,72,1105,1,73,1,11,15,49934,1102,1,98369,66,1101,1,0,67,1102,1,1948,68,1102,1,556,69,1101,0,1,71,1101,0,1950,72,1105,1,73,1,125,49,15231,1102,85091,1,66,1101,1,0,67,1101,0,1979,68,1102,1,556,69,1102,1,2,71,1102,1,1981,72,1106,0,73,1,19,14,23428,48,170726,1102,92899,1,66,1101,0,2,67,1101,2012,0,68,1101,351,0,69,1101,0,1,71,1101,2016,0,72,1106,0,73,0,0,0,0,255,68891,1101,0,5857,66,1101,0,4,67,1102,1,2045,68,1102,302,1,69,1101,1,0,71,1101,2053,0,72,1105,1,73,0,0,0,0,0,0,0,0,16,19861,1101,7879,0,66,1102,2,1,67,1101,0,2082,68,1101,302,0,69,1101,0,1,71,1102,1,2086,72,1105,1,73,0,0,0,0,15,24967,1102,1,52861,66,1102,2,1,67,1102,1,2115,68,1101,0,302,69,1102,1,1,71,1102,1,2119,72,1105,1,73,0,0,0,0,11,44893,1101,0,31081,66,1101,0,1,67,1101,2148,0,68,1101,556,0,69,1102,1,1,71,1102,2150,1,72,1106,0,73,1,160,35,522906,1101,44497,0,66,1102,1,1,67,1102,1,2179,68,1102,1,556,69,1102,3,1,71,1102,1,2181,72,1106,0,73,1,2,48,256089,35,261453,35,435755,1102,81157,1,66,1102,1,1,67,1102,2214,1,68,1102,556,1,69,1101,0,1,71,1102,1,2216,72,1105,1,73,1,107,48,85363,1102,1,599,66,1102,1,2,67,1102,2245,1,68,1101,0,302,69,1102,1,1,71,1102,2249,1,72,1105,1,73,0,0,0,0,4,52861 From 71f54bac6b8af9336fc81066ce4eb947a40342d9 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 16 Oct 2021 17:46:55 +0200 Subject: [PATCH 33/37] Add minimal day 25 runner --- 2019/aoc2019/day25.py | 55 +++++++++++++++++++++++++++++++++++++++++++ 2019/inputs/25.txt | 1 + 2 files changed, 56 insertions(+) create mode 100644 2019/aoc2019/day25.py create mode 100644 2019/inputs/25.txt diff --git a/2019/aoc2019/day25.py b/2019/aoc2019/day25.py new file mode 100644 index 0000000..9cebf1f --- /dev/null +++ b/2019/aoc2019/day25.py @@ -0,0 +1,55 @@ +from typing import TextIO + +from aoc2019.intcode import read_program, Computer + + +def print_output(computer: Computer): + output = "" + + while len(computer.output): + output += chr(computer.get_output()) + + print(output, end='') + + +def load_save(save, computer: Computer): + computer.pointer, computer.relative_base, computer.program = save + + +def create_save(computer: Computer): + return computer.pointer, computer.relative_base, computer.program.copy() + + +def part1(data: TextIO): + print("This day must use a file as input as it requires the stdin for other things.") + + computer = Computer(read_program(data)) + + saves = {} + + while True: + try: + computer.run() + print_output(computer) + + print("detected a death, loading auto save...") + load_save(saves['auto'], computer) + print("Command?") + except IndexError: + pass + + print_output(computer) + + saves['auto'] = create_save(computer) + + command = input().strip() + + if command == "exit": + return + # TODO: add manual save states. + + for c in command: + computer.send_input(ord(c)) + + computer.send_input(10) # manually send newline + diff --git a/2019/inputs/25.txt b/2019/inputs/25.txt new file mode 100644 index 0000000..c36b9c5 --- /dev/null +++ b/2019/inputs/25.txt @@ -0,0 +1 @@ +109,4806,21101,0,3124,1,21102,13,1,0,1105,1,1424,21102,166,1,1,21102,24,1,0,1105,1,1234,21101,31,0,0,1106,0,1984,1106,0,13,6,4,3,2,52,51,21,4,28,56,55,3,19,-9,-10,47,89,88,90,90,6,77,73,85,71,1,76,68,63,65,22,-27,70,76,81,87,5,105,105,107,108,95,4,97,92,109,109,5,110,105,110,108,95,4,115,96,109,109,13,-3,59,101,85,92,97,13,84,80,92,78,34,-15,26,-16,46,88,72,79,84,0,72,76,-3,85,74,79,75,-8,64,68,75,57,65,70,64,66,72,8,-41,32,-22,56,77,82,-4,60,76,62,70,-2,74,-11,55,52,68,67,73,56,60,52,-20,44,56,66,-24,48,58,42,49,54,-16,-53,10,0,56,99,96,95,82,94,83,45,-9,23,-13,61,85,88,74,71,82,73,79,73,89,67,65,-4,62,73,70,69,56,68,57,2,-35,24,-14,64,85,90,4,70,67,79,7,83,-2,68,75,-5,78,65,57,75,-10,76,53,76,0,-37,31,-21,57,78,83,-3,64,74,72,0,76,-9,73,58,57,-13,70,57,49,67,-18,54,64,48,55,-23,48,44,56,42,-14,-51,14,-4,74,95,100,14,97,77,86,79,9,92,79,75,5,27,-17,61,82,87,1,68,78,76,4,80,-5,66,58,78,60,-10,73,60,52,70,-15,57,67,51,58,-6,-43,14,-4,74,95,100,14,81,94,90,90,9,92,79,75,5,60,-50,23,42,38,-32,38,39,30,42,47,-38,30,36,28,25,41,38,34,31,18,23,29,19,33,-52,20,29,-55,27,27,27,8,15,-61,22,16,-64,24,13,18,-54,-69,-70,-14,7,12,-74,-8,-11,1,-71,5,-80,-4,-3,3,-15,-84,-85,-109,29,-19,59,80,85,-1,82,62,71,64,-6,77,64,60,-10,62,66,57,59,63,57,67,51,-19,56,58,57,57,-10,-47,44,-34,39,58,54,-16,60,61,57,64,48,56,-23,52,40,60,38,-28,44,53,-31,55,32,55,-35,48,42,41,-39,32,38,42,-42,-44,12,33,38,-48,28,19,25,32,-52,-76,-77,59,-49,13,55,-30,42,51,-33,49,50,32,31,31,39,36,48,-42,24,35,32,34,29,21,35,19,25,37,-53,14,10,26,18,-57,-59,-3,18,23,-63,1,17,3,-67,1,-4,14,-2,6,-73,-8,14,-76,-12,-78,-40,2,4,-13,-82,-106,-107,35,-25,53,74,79,0,74,60,-10,65,53,72,64,52,56,52,50,-19,53,57,62,56,-24,58,54,38,39,40,-29,-31,2,56,35,-34,-58,-59,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-94,-98,-103,-83,-97,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-90,-94,-97,-97,-86,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,263,-253,-199,-233,-158,-156,-151,-169,-226,-239,-158,-162,-176,-164,-160,-172,-179,-247,-162,-170,-177,-184,-183,-253,-171,-190,-167,-174,-258,-257,-227,-183,-197,-187,-175,-182,-193,-184,-268,-202,-191,-194,-192,-197,-205,-191,-207,-276,-278,-222,-201,-196,-282,-206,-219,-196,-286,-207,-206,-210,-223,-222,-223,-225,-280,-293,-296,-232,-220,-231,-300,-212,-223,-218,-304,-236,-228,-223,-239,-227,-310,-227,-240,-244,-314,-248,-237,-250,-243,-239,-247,-237,-308,-345,-273,-260,-248,-243,-263,-329,-252,-252,-248,-260,-267,-266,-253,-337,-249,-260,-255,-259,-342,-260,-267,-280,-270,-271,-348,-281,-268,-272,-279,-285,-342,-355,-280,-278,-279,-284,-277,-361,-282,-278,-274,-275,-290,-298,-300,-369,-300,-292,-290,-373,-309,-375,-299,-298,-301,-310,-302,-297,-370,-383,-302,-316,-321,-311,-315,-299,-321,-308,-392,-306,-322,-330,-312,-397,-326,-334,-317,-401,-330,-338,-324,-325,-337,-329,-339,-341,-398,-411,-347,-335,-346,-415,-334,-352,-350,-346,-341,-338,-422,-334,-345,-340,-344,-427,-345,-357,-357,-351,-432,-365,-361,-353,-367,-370,-354,-363,-351,-427,-464,-441,-397,-373,-434,-447,-376,-380,-374,-375,-373,-452,-454,-398,-377,-372,-458,-376,-388,-382,-377,-387,-396,-465,-400,-398,-468,-404,-404,-395,-403,-473,-390,-396,-476,-406,-409,-395,-480,-408,-404,-483,-418,-396,-486,-403,-399,-409,-417,-413,-421,-493,37,-5,73,71,-8,75,62,58,-12,62,55,74,64,48,50,-19,45,63,-22,61,48,44,-26,50,37,44,48,-31,33,40,48,41,43,30,37,-25,-38,-63,0,0,109,7,21101,0,0,-2,22208,-2,-5,-1,1205,-1,1169,22202,-2,-4,1,22201,1,-6,1,22102,1,-2,2,21101,0,1162,0,2106,0,-3,21201,-2,1,-2,1106,0,1136,109,-7,2105,1,0,109,6,2102,1,-5,1181,21002,0,1,-2,21101,0,0,-3,21201,-5,1,-5,22208,-3,-2,-1,1205,-1,1229,2201,-5,-3,1204,21001,0,0,1,22102,1,-3,2,22101,0,-2,3,21101,0,1222,0,2105,1,-4,21201,-3,1,-3,1106,0,1192,109,-6,2106,0,0,109,2,21201,-1,0,1,21102,1256,1,2,21102,1,1251,0,1105,1,1174,109,-2,2106,0,0,109,5,22201,-4,-3,-1,22201,-2,-1,-1,204,-1,109,-5,2106,0,0,109,3,2101,0,-2,1280,1006,0,1303,104,45,104,32,1201,-1,66,1292,20101,0,0,1,21102,1,1301,0,1106,0,1234,104,10,109,-3,2105,1,0,0,0,109,2,1202,-1,1,1309,1101,0,0,1308,21101,4601,0,1,21102,13,1,2,21101,0,4,3,21101,0,1353,4,21102,1343,1,0,1106,0,1130,20102,1,1308,-1,109,-2,2106,0,0,74,109,3,1202,-2,1,1360,20008,0,1309,-1,1206,-1,1419,1005,1308,1398,1101,0,1,1308,21008,1309,-1,-1,1206,-1,1387,21102,1,106,1,1105,1,1391,21101,0,92,1,21102,1,1398,0,1105,1,1234,104,45,104,32,1201,-2,1,1408,20102,1,0,1,21101,1417,0,0,1105,1,1234,104,10,109,-3,2105,1,0,109,3,1201,-2,0,1128,21101,0,34,1,21101,0,1441,0,1106,0,1234,1001,1128,0,1446,21002,0,1,1,21101,1456,0,0,1106,0,1234,21102,1,41,1,21102,1467,1,0,1105,1,1234,1001,1128,1,1473,20102,1,0,1,21102,1,1482,0,1105,1,1234,21102,46,1,1,21102,1,1493,0,1105,1,1234,21001,1128,3,1,21102,4,1,2,21102,1,1,3,21101,1273,0,4,21102,1,1516,0,1106,0,1130,21001,1128,0,1,21101,0,1527,0,1106,0,1310,1001,1128,2,1533,20101,0,0,-1,1206,-1,1545,21101,0,1545,0,2105,1,-1,109,-3,2106,0,0,109,0,99,109,2,1102,0,1,1550,21101,0,4601,1,21102,1,13,2,21102,4,1,3,21102,1,1664,4,21101,0,1582,0,1106,0,1130,2,2486,1352,1551,1102,0,1,1552,20102,1,1550,1,21102,1,33,2,21102,1,1702,3,21101,1609,0,0,1105,1,2722,21007,1552,0,-1,1205,-1,1630,20107,0,1552,-1,1205,-1,1637,21102,1630,1,0,1105,1,1752,21102,548,1,1,1105,1,1641,21101,0,687,1,21102,1,1648,0,1105,1,1234,21101,4457,0,1,21102,1,1659,0,1106,0,1424,109,-2,2106,0,0,109,4,21202,-2,-1,-2,2101,0,-3,1675,21008,0,-1,-1,1206,-1,1697,1201,-3,2,1687,20101,-27,0,-3,22201,-3,-2,-3,2001,1550,-3,1550,109,-4,2105,1,0,109,5,21008,1552,0,-1,1206,-1,1747,1201,-3,1901,1717,20102,1,0,-2,1205,-4,1736,20207,-2,1551,-1,1205,-1,1747,1102,1,-1,1552,1106,0,1747,22007,1551,-2,-1,1205,-1,1747,1101,0,1,1552,109,-5,2105,1,0,109,1,21102,1,826,1,21102,1,1765,0,1106,0,1234,21001,1550,0,1,21102,1,1776,0,1105,1,2863,21102,1090,1,1,21101,0,1787,0,1106,0,1234,99,1105,1,1787,109,-1,2106,0,0,109,1,21102,512,1,1,21102,1,1809,0,1105,1,1234,99,1105,1,1809,109,-1,2106,0,0,109,1,1102,1,1,1129,109,-1,2106,0,0,109,1,21101,377,0,1,21101,0,1842,0,1105,1,1234,1105,1,1831,109,-1,2105,1,0,109,1,21102,1,407,1,21102,1863,1,0,1106,0,1234,99,1105,1,1863,109,-1,2105,1,0,109,1,21101,452,0,1,21101,1885,0,0,1106,0,1234,99,1106,0,1885,109,-1,2105,1,0,1941,1947,1953,1958,1965,1972,1978,4575,4923,4527,4604,5024,5218,4671,4646,5043,4683,5005,4580,4541,5168,4938,4981,4562,4602,4852,5202,4609,4790,5221,5228,5072,4959,5090,4803,4541,5076,4608,5006,4867,2281,2468,2418,2450,2487,2125,2505,5,95,108,104,104,23,5,96,91,108,108,1,4,101,105,112,3,6,104,104,106,107,94,-1,6,109,104,109,107,94,-1,5,111,91,100,93,23,5,114,95,108,108,1,109,3,21101,0,1993,0,1106,0,2634,1006,1129,2010,21102,1,316,1,21102,2007,1,0,1105,1,1234,1105,1,2076,21101,0,0,-1,1201,-1,1894,2019,21002,0,1,1,21101,0,0,2,21101,0,0,3,21101,0,2037,0,1106,0,2525,1206,1,2054,1201,-1,1934,2050,21101,2051,0,0,106,0,0,1105,1,2076,21201,-1,1,-1,21207,-1,7,-2,1205,-2,2014,21101,0,177,1,21101,2076,0,0,1105,1,1234,109,-3,2106,0,0,109,3,2001,1128,-2,2088,21002,0,1,-1,1205,-1,2108,21101,0,201,1,21101,0,2105,0,1105,1,1234,1105,1,2119,21201,-1,0,1,21101,2119,0,0,1105,1,1424,109,-3,2105,1,0,0,109,1,1101,0,0,2124,21101,4601,0,1,21102,1,13,2,21102,4,1,3,21102,2173,1,4,21101,0,2154,0,1105,1,1130,1005,2124,2168,21102,226,1,1,21102,1,2168,0,1106,0,1234,109,-1,2105,1,0,109,3,1005,2124,2275,1201,-2,0,2183,20008,0,1128,-1,1206,-1,2275,1201,-2,1,2195,20102,1,0,-1,21201,-1,0,1,21102,1,5,2,21101,1,0,3,21101,0,2216,0,1106,0,2525,1206,1,2275,21101,0,258,1,21101,2230,0,0,1105,1,1234,22102,1,-1,1,21101,0,2241,0,1106,0,1234,104,46,104,10,1102,1,1,2124,1201,-2,0,2256,1101,-1,0,0,1201,-2,3,2263,20102,1,0,-1,1206,-1,2275,21102,2275,1,0,2106,0,-1,109,-3,2105,1,0,0,109,1,1102,1,0,2280,21102,1,4601,1,21101,13,0,2,21101,0,4,3,21101,0,2329,4,21101,2310,0,0,1105,1,1130,1005,2280,2324,21102,1,273,1,21102,1,2324,0,1106,0,1234,109,-1,2105,1,0,109,3,1005,2280,2413,1201,-2,0,2339,21008,0,-1,-1,1206,-1,2413,1201,-2,1,2350,21001,0,0,-1,21201,-1,0,1,21102,5,1,2,21101,0,1,3,21102,1,2372,0,1106,0,2525,1206,1,2413,21101,301,0,1,21102,2386,1,0,1105,1,1234,22101,0,-1,1,21102,2397,1,0,1106,0,1234,104,46,104,10,1101,0,1,2280,1201,-2,0,2412,102,1,1128,0,109,-3,2106,0,0,109,1,21102,-1,1,1,21102,2431,1,0,1105,1,1310,1205,1,2445,21101,133,0,1,21102,2445,1,0,1106,0,1234,109,-1,2106,0,0,109,1,21101,3,0,1,21101,2463,0,0,1105,1,2081,109,-1,2106,0,0,109,1,21102,1,4,1,21101,0,2481,0,1105,1,2081,109,-1,2105,1,0,70,109,1,21102,5,1,1,21102,2500,1,0,1106,0,2081,109,-1,2105,1,0,109,1,21102,1,6,1,21101,0,2518,0,1106,0,2081,109,-1,2106,0,0,0,0,109,5,1201,-3,0,2523,1101,0,1,2524,21201,-4,0,1,21102,1,2585,2,21101,2550,0,0,1106,0,1174,1206,-2,2576,1202,-4,1,2558,2001,0,-3,2566,101,3094,2566,2566,21008,0,-1,-1,1205,-1,2576,1102,1,0,2524,21001,2524,0,-4,109,-5,2106,0,0,109,5,22201,-4,-3,-4,22201,-4,-2,-4,21208,-4,10,-1,1206,-1,2606,21101,0,-1,-4,201,-3,2523,2615,1001,2615,3094,2615,21002,0,1,-1,22208,-4,-1,-1,1205,-1,2629,1101,0,0,2524,109,-5,2105,1,0,109,4,21102,3094,1,1,21102,1,30,2,21102,1,1,3,21102,2706,1,4,21101,2659,0,0,1105,1,1130,21101,0,0,-3,203,-2,21208,-2,10,-1,1205,-1,2701,21207,-2,0,-1,1205,-1,2663,21207,-3,29,-1,1206,-1,2663,2101,3094,-3,2693,2101,0,-2,0,21201,-3,1,-3,1106,0,2663,109,-4,2105,1,0,109,2,2101,0,-1,2715,1101,-1,0,0,109,-2,2106,0,0,0,109,5,2102,1,-2,2721,21207,-4,0,-1,1206,-1,2739,21102,0,1,-4,22101,0,-4,1,22101,0,-3,2,21101,1,0,3,21101,2758,0,0,1106,0,2763,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,2786,22207,-5,-3,-1,1206,-1,2786,22101,0,-5,-5,1105,1,2858,22102,1,-5,1,21201,-4,-1,2,21202,-3,2,3,21101,0,2805,0,1105,1,2763,21202,1,1,-5,21101,0,1,-2,22207,-5,-3,-1,1206,-1,2824,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2850,21202,-2,1,1,21201,-4,-1,2,21101,0,2850,0,106,0,2721,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0,109,3,21208,-2,0,-1,1205,-1,2902,21207,-2,0,-1,1205,-1,2882,1106,0,2888,104,45,21202,-2,-1,-2,22101,0,-2,1,21102,1,2899,0,1105,1,2909,1106,0,2904,104,48,109,-3,2105,1,0,109,4,22101,0,-3,1,21101,10,0,2,21101,0,2926,0,1106,0,3010,22101,0,1,-2,22101,0,2,-1,1206,-2,2948,22102,1,-2,1,21101,2948,0,0,1106,0,2909,22101,48,-1,-1,204,-1,109,-4,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21102,1,0,-4,21101,0,0,-3,21102,1,51,-2,21201,-2,-1,-2,1201,-2,2959,3033,21002,0,1,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,3059,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,3078,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,3024,21202,-4,1,-7,22102,1,-3,-6,109,-8,2106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3131,3143,0,3821,3405,3252,0,11,61,105,95,94,17,50,97,83,78,79,83,108,-19,2,7,-79,-9,-2,2,-83,-11,-7,-86,-3,-16,-7,-11,-6,-21,-21,-94,-30,-96,-25,-19,-23,-31,-101,-29,-25,-104,-21,-34,-38,-108,-39,-34,-32,-33,-31,-114,-43,-47,-35,-49,-105,-120,-69,-43,-123,-49,-56,-57,-47,-128,-40,-51,-46,-50,-133,-51,-63,-63,-57,-138,-69,-58,-62,-65,-143,-79,-69,-63,-68,-148,-79,-68,-82,-83,-63,-81,-77,-85,-145,-158,-75,-88,-92,-162,-91,-85,-89,-97,-167,-96,-104,-87,-171,-106,-104,-105,-97,-176,-94,-109,-114,-104,-112,-114,-169,3259,3268,0,3124,0,3341,0,8,75,96,89,96,20,53,83,106,72,11,44,38,37,35,37,38,36,-48,17,29,33,20,-53,-4,14,12,-44,-12,20,23,8,6,-63,-14,4,7,11,0,0,-1,11,-72,4,-5,-7,-3,-10,-5,-1,-11,-81,-17,-5,-16,-85,-4,-18,-17,-4,-14,-26,-10,-93,-12,-26,-23,-19,-30,-30,-31,-19,-102,-26,-35,-37,-33,-40,-35,-31,-41,-97,3348,3356,0,3252,0,3922,3771,7,76,108,102,104,86,91,88,48,36,55,51,-19,46,58,66,46,59,-25,48,58,55,55,-30,36,47,45,50,30,37,41,-38,38,39,41,27,-43,22,34,42,22,35,-35,-50,-51,-2,16,13,30,26,26,15,27,9,15,27,-49,3412,3421,0,3478,3714,0,3124,8,64,102,98,100,88,88,85,92,56,27,54,51,42,51,49,39,-31,51,36,35,42,47,-37,46,40,-40,31,23,43,25,-45,30,22,22,35,-50,22,32,-53,25,23,-56,27,14,10,-60,-22,11,2,14,19,-66,-28,14,4,-2,-71,11,-4,10,9,-3,1,-7,-65,3485,3493,0,3645,0,3405,3570,7,65,89,99,98,108,85,108,76,8,27,27,36,-48,16,32,18,13,-53,18,10,27,-57,8,10,9,17,-62,16,16,19,7,10,5,21,-1,-3,-72,-3,5,7,-76,6,1,-2,-11,3,-10,-10,-6,-14,-59,-87,1,-10,-5,-84,-10,-24,-94,-21,-11,-14,-14,-99,-22,-22,-18,-103,-23,-20,-33,-23,-39,-109,-27,-26,-30,-44,-114,-28,-44,-52,-34,-105,3577,3589,0,0,3478,4218,4289,11,72,87,92,87,95,83,84,14,57,77,77,55,34,55,60,-26,56,41,40,-30,38,54,40,34,34,42,30,31,-39,32,28,40,26,-44,34,24,-47,32,33,29,33,27,31,35,25,13,-57,22,20,16,28,15,6,18,-65,2,2,15,4,1,7,-72,14,5,7,-1,-63,3652,3673,0,0,0,3478,0,20,51,84,80,93,8,62,88,70,84,83,75,79,71,-1,33,66,74,79,63,75,40,32,70,77,-11,57,63,69,54,-16,51,61,-19,69,58,63,-23,63,57,39,53,-28,51,52,38,51,36,44,49,47,-37,41,39,-40,43,30,26,-44,26,33,-16,3721,3735,0,3880,0,0,3405,13,54,100,86,103,15,63,98,77,93,94,78,90,90,35,49,68,64,-6,59,61,59,73,-11,53,69,55,-15,49,59,58,-19,64,58,57,-23,59,52,39,49,48,-29,40,48,50,-33,55,44,49,-23,3778,3786,0,4122,3341,0,0,7,76,108,88,88,97,89,102,34,48,66,69,73,62,62,61,73,3,72,61,77,55,53,-2,-17,34,53,49,68,-15,59,45,-25,39,49,48,-29,39,46,48,51,55,-21,3828,3851,0,0,0,3124,0,22,50,88,92,7,41,77,83,70,81,77,65,83,67,-3,34,74,79,71,76,56,63,67,28,55,82,79,70,72,78,85,9,-4,68,78,0,75,-9,73,73,61,63,62,-15,71,62,64,56,53,57,49,-9,3887,3895,0,0,0,3714,3977,7,68,97,107,89,93,89,97,26,43,91,73,85,91,85,72,72,76,68,3,78,-6,63,74,60,59,79,57,0,54,67,57,52,50,-5,3929,3936,0,3341,4057,0,0,6,59,107,91,88,90,90,40,38,70,68,58,-12,66,56,-15,68,55,51,-19,47,44,44,50,54,44,58,56,-28,54,39,38,45,-33,50,44,-36,35,27,47,29,-41,38,36,43,24,36,-33,3984,3996,0,0,3880,0,0,11,68,86,102,87,99,102,80,98,92,94,100,60,24,43,39,51,37,-33,31,47,33,-37,27,-39,30,28,45,-43,40,24,30,22,35,18,29,29,17,30,-27,-55,28,15,11,30,-53,21,7,-63,1,11,10,-67,-2,10,6,13,-3,-5,-74,-7,3,10,0,-67,-80,3,-10,-4,1,-14,-14,-73,4064,4087,0,0,0,0,3922,22,65,74,90,87,6,41,86,76,88,70,0,44,63,70,74,79,63,71,57,69,57,58,34,39,81,-4,60,74,73,61,56,72,72,-12,71,65,-15,50,52,-18,68,59,61,53,50,54,46,-26,51,51,53,47,34,44,43,55,-21,4129,4140,0,4385,0,3771,0,10,68,86,106,92,89,82,100,88,93,91,77,6,38,18,36,36,33,-25,-52,-2,30,27,9,21,10,10,8,-47,-62,-15,12,4,-1,16,1,-69,13,14,8,7,2,14,-76,0,-9,-14,3,4,0,-14,-7,-16,-8,-3,-5,-89,-20,-9,-13,-16,-94,-25,-23,-27,-14,-10,-100,-18,-18,-38,-22,-22,-106,-23,-29,-109,-28,-42,-45,-48,-38,-42,-50,-35,-53,-35,-51,-107,4225,4237,0,3570,0,0,0,11,58,98,90,91,95,85,84,96,86,90,82,51,38,59,64,-22,60,45,44,-26,38,-28,58,42,42,52,36,32,44,29,45,30,-39,47,32,42,29,-44,35,30,18,30,34,-50,19,27,29,-54,-4,24,25,15,19,11,7,20,16,9,3,-66,19,-50,-55,4296,4305,0,0,3570,0,0,8,59,102,104,103,93,87,97,99,79,5,24,20,-50,26,17,31,11,21,-56,30,7,17,16,22,-62,2,14,3,-66,17,4,0,-70,6,-3,11,-9,1,-76,-7,-2,0,-1,1,-82,-18,-2,-16,-86,-4,-12,-16,-19,-19,-8,-17,-5,-95,-28,-24,-28,-29,-31,-19,-33,-25,-20,-105,-39,-28,-32,-30,-28,-28,-98,-113,-67,-33,-116,-52,-36,-50,-120,-37,-50,-54,-35,-94,4392,4401,0,4457,0,4122,0,8,72,88,105,104,85,90,87,100,55,29,48,44,63,-20,54,40,-30,34,-32,43,39,49,48,39,31,-39,44,46,31,40,40,44,-46,18,30,19,-50,32,32,12,28,29,17,21,13,-59,24,18,-62,13,15,14,9,-67,-3,7,6,-71,-7,3,-1,0,-7,-63,4464,4484,0,0,4556,4385,0,19,64,81,78,95,91,81,91,95,5,39,75,71,68,75,79,77,70,74,79,71,2,38,-41,42,29,25,-45,32,22,40,35,-50,31,27,26,23,-43,-56,8,-58,21,22,8,21,20,21,17,3,-54,15,0,8,12,1,11,-1,11,-7,-77,-8,-3,-1,-2,0,-83,3,-12,-10,-11,-88,-3,-21,-9,-19,-23,-5,-95,-7,-18,-13,-17,-100,-28,-34,-34,-26,-21,-33,-23,-19,-95,4563,4588,1553,0,0,0,4457,24,56,89,75,88,87,88,84,70,13,50,67,75,79,68,78,66,78,60,-10,27,64,66,65,67,12,53,97,83,93,105,105,87,91,83,25,24,23,4122,4653,131099,0,4057,4662,28,1829,3405,4676,2147483677,0,4289,4684,8222,0,3821,4704,31,1818,4218,4724,524320,0,3252,4733,33,1872,3771,4741,34,1850,3714,4753,547,0,3645,4762,134217764,0,4385,4771,37,1796,3977,4782,1062,0,3922,4794,55,0,8,101,102,100,100,96,92,102,89,13,92,96,87,89,93,87,97,81,11,86,88,87,87,7,90,102,107,91,99,98,84,19,78,95,95,92,88,86,72,91,89,4,76,69,70,0,66,80,66,61,72,19,84,85,76,88,93,8,76,82,74,71,87,84,80,77,64,69,75,65,79,8,96,102,98,100,91,101,83,94,7,105,96,102,106,100,98,102,11,98,99,95,102,86,94,15,90,78,98,76,8,103,105,100,86,97,88,96,101,8,89,106,106,90,102,92,101,92,10,91,104,87,84,98,86,16,95,93,81,11,91,93,107,87,85,16,95,93,86,90,95,11,89,85,101,93,17,93,80,98,97,81,93 From e66f3df94910618ed4fa74cf99be4491e2d63b51 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 18 Oct 2021 15:51:44 +0200 Subject: [PATCH 34/37] Implement brute force for 2019 day 25 --- 2019/aoc2019/day25.py | 77 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 9 deletions(-) diff --git a/2019/aoc2019/day25.py b/2019/aoc2019/day25.py index 9cebf1f..3aff0e2 100644 --- a/2019/aoc2019/day25.py +++ b/2019/aoc2019/day25.py @@ -1,9 +1,15 @@ -from typing import TextIO +import itertools +from typing import TextIO, Iterable, Tuple, Set from aoc2019.intcode import read_program, Computer -def print_output(computer: Computer): +def powerset(iterable: Iterable) -> Iterable[Tuple]: + s = list(iterable) + return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s) + 1)) + + +def print_output(computer: Computer) -> str: output = "" while len(computer.output): @@ -11,6 +17,8 @@ def print_output(computer: Computer): print(output, end='') + return output + def load_save(save, computer: Computer): computer.pointer, computer.relative_base, computer.program = save @@ -20,10 +28,40 @@ def create_save(computer: Computer): return computer.pointer, computer.relative_base, computer.program.copy() +def send_command(computer: Computer, command: str): + for c in command: + computer.send_input(ord(c)) + + computer.send_input(10) # manually send newline + + +def force(computer: Computer, direction: str, items: Set[str]): + for combination in powerset(items): + # Drop everything, disregard what's on the ground + for item in items: + send_command(computer, f"drop {item}") + + # Now pick up whatever we want to try + for item in combination: + send_command(computer, f"take {item}") + + send_command(computer, direction) + + try: + computer.run() + print_output(computer) + return True + except IndexError: + print_output(computer) + + return False + + def part1(data: TextIO): print("This day must use a file as input as it requires the stdin for other things.") computer = Computer(read_program(data)) + items = set() saves = {} @@ -42,14 +80,35 @@ def part1(data: TextIO): saves['auto'] = create_save(computer) - command = input().strip() + try: + command = input().strip() + except EOFError: + return "exiting" if command == "exit": - return - # TODO: add manual save states. + return "exiting" + elif command == "items": + print(items) + continue + elif command.startswith("save "): + save_name = command.removeprefix("save ") + saves[save_name] = create_save(computer) + print(f"Saved game state as {save_name}") + continue + elif command.startswith("load "): + save_name = command.removeprefix("load ") + load_save(saves[save_name], computer) + print(f"Loaded game state from {save_name}") + continue + elif command.startswith("take "): + items.add(command.removeprefix("take ")) + elif command.startswith("drop "): + items.remove(command.removeprefix("drop ")) + elif command.startswith("force "): + direction = command.removeprefix("force ") + if force(computer, direction, items): + return + continue - for c in command: - computer.send_input(ord(c)) - - computer.send_input(10) # manually send newline + send_command(computer, command) From 579176041217f513d338e9d368921c2ba8fd8b7e Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 18 Oct 2021 16:00:32 +0200 Subject: [PATCH 35/37] More efficiently pick items --- 2019/aoc2019/day25.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/2019/aoc2019/day25.py b/2019/aoc2019/day25.py index 3aff0e2..2efa500 100644 --- a/2019/aoc2019/day25.py +++ b/2019/aoc2019/day25.py @@ -36,14 +36,22 @@ def send_command(computer: Computer, command: str): def force(computer: Computer, direction: str, items: Set[str]): - for combination in powerset(items): - # Drop everything, disregard what's on the ground - for item in items: - send_command(computer, f"drop {item}") + # First, drop everything + for item in items: + send_command(computer, f"drop {item}") - # Now pick up whatever we want to try + holding = tuple() + + for combination in powerset(items): + # drop everything we don't want to keep holding + for item in holding: + if item not in combination: + send_command(computer, f"drop {item}") + + # pick up what we want to pick up for item in combination: - send_command(computer, f"take {item}") + if item not in holding: + send_command(computer, f"take {item}") send_command(computer, direction) @@ -53,6 +61,7 @@ def force(computer: Computer, direction: str, items: Set[str]): return True except IndexError: print_output(computer) + holding = combination return False @@ -107,7 +116,7 @@ def part1(data: TextIO): elif command.startswith("force "): direction = command.removeprefix("force ") if force(computer, direction, items): - return + return "success" continue send_command(computer, command) From ef302bbeb7da4249287747ea17943ccdaa53f232 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 18 Oct 2021 19:45:36 +0200 Subject: [PATCH 36/37] Trivial reimplementation day 21 --- 2019/aoc2019/day21.py | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 2019/aoc2019/day21.py diff --git a/2019/aoc2019/day21.py b/2019/aoc2019/day21.py new file mode 100644 index 0000000..d96c197 --- /dev/null +++ b/2019/aoc2019/day21.py @@ -0,0 +1,44 @@ +from typing import TextIO + +from aoc2019.intcode import read_program, Computer + + +def send_input(computer: Computer, program: str) -> None: + for c in program: + computer.send_input(ord(c)) + + +def run(data: TextIO, program: str) -> int: + computer = Computer(read_program(data)) + + send_input(computer, program) + computer.run() + + return computer.output.pop() + + +def part1(data: TextIO) -> int: + program = """\ + OR A J + AND B J + AND C J + NOT J J + AND D J + WALK + """ + + return run(data, program) + + +def part2(data: TextIO) -> int: + program = """\ + NOT H J + OR C J + AND A J + AND B J + NOT J J + AND D J + RUN + """ + + return run(data, program) From 583b590a6cf653ca353728c170283be202793edb Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Mon, 18 Oct 2021 21:50:22 +0200 Subject: [PATCH 37/37] Remove last C++ remnant. --- 2019/CMakeLists.txt | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 2019/CMakeLists.txt diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt deleted file mode 100644 index 69c855e..0000000 --- a/2019/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.12) - -project(aoc2019) - -find_package(GTest REQUIRED) - -option(ANIMATE_DAY13 "Animate the Arkanoid game in day 13." Off) - -file(GLOB DAYS_FILES src/day*.cpp) -add_library(AoCSolutions src/implementations.cpp "${DAYS_FILES}" src/point.hpp src/utils.cpp src/utils.hpp) -target_compile_features(AoCSolutions PUBLIC cxx_std_17) - -if (ANIMATE_DAY13) - target_compile_definitions(AoCSolutions ANIMATE_DAY13) -endif () - -add_executable(runner src/runner.cpp) -target_compile_features(runner PUBLIC cxx_std_17) -target_link_libraries(runner AoCSolutions) - -add_executable(unit_tests tests/test_solutions.cpp tests/test_intcode.cpp) -target_compile_features(unit_tests PUBLIC cxx_std_17) -target_link_libraries(unit_tests AoCSolutions GTest::GTest GTest::Main) -target_compile_definitions(unit_tests PRIVATE "TEST_SAMPLES_DIR=\"${CMAKE_SOURCE_DIR}/tests/samples\"") -target_include_directories(unit_tests PRIVATE "${CMAKE_SOURCE_DIR}/src") - -enable_testing() -gtest_discover_tests(unit_tests NO_PRETTY_VALUES)