From 061377803618fb084aa73a45af95f2c0595ea2f4 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 7 Dec 2019 16:39:41 +0100 Subject: [PATCH] Very ugly solution to part 2. --- 2019/src/day07.cpp | 166 ++++++++++++++++++++++++++++++++-- 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 + 5 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 2019/tests/samples/07-2-1.in create mode 100644 2019/tests/samples/07-2-1.out create mode 100644 2019/tests/samples/07-2-2.in create mode 100644 2019/tests/samples/07-2-2.out diff --git a/2019/src/day07.cpp b/2019/src/day07.cpp index 07bb868..1fe4ef3 100644 --- a/2019/src/day07.cpp +++ b/2019/src/day07.cpp @@ -1,23 +1,168 @@ +#include #include +#include #include "days.hpp" #include "utils.hpp" -namespace { - int simulate(const std::vector& program, const std::vector phases) { +namespace { + class IntCodeComputer { + public: + explicit IntCodeComputer(std::vector program, std::deque initial_inputs) : + program{std::move(program)}, inputs{std::move(initial_inputs)} { + } + + void run() { + while (ip < program.size()) { + switch (program[ip] % 100) { + case 1: + program[program[ip + 3]] = interpret_value(1) + interpret_value(2); + ip += 4; + break; + + case 2: + program[program[ip + 3]] = interpret_value(1) * interpret_value(2); + ip += 4; + break; + + case 3: + if (inputs.empty()) { + return; + } + + program[program[ip + 1]] = inputs.front(); + inputs.pop_front(); + ip += 2; + break; + + case 4: + outputSink->sendInput(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: // equality + program[program[ip + 3]] = interpret_value(1) < interpret_value(2); + ip += 4; + break; + + case 8: // less than + program[program[ip + 3]] = interpret_value(1) == interpret_value(2) ? 1 : 0; + ip += 4; + 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); + } + } + } + + void sendInput(int input) { + inputs.push_back(input); + } + + void connectOutput(IntCodeComputer &computer) { + outputSink = &computer; + } + + [[nodiscard]] bool isTerminated() const { + return halted; + } + + [[nodiscard]] const std::deque ¤tInputs() const { + return inputs; + } + + private: + std::vector program; + std::deque inputs = {}; + IntCodeComputer *outputSink = nullptr; + int ip = 0; + bool halted = false; + + [[nodiscard]] int interpret_value(int pos) const { + bool 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"); + } + + if (immediate) { + return program[ip + pos]; + } else { + return program[program[ip + pos]]; + } + } + }; + + int simulate(const std::vector &program, const std::array &phases) { int state = 0; for (int phase : phases) { auto copy = program; - auto result = aoc2019::run_intcode(copy, { phase, state }); + auto result = aoc2019::run_intcode(copy, {phase, state}); state = result.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::read_intcode(input); - std::vector phases{0, 1, 2, 3, 4}; + std::array phases{0, 1, 2, 3, 4}; int best = 0; @@ -25,9 +170,18 @@ void aoc2019::day07_part1(std::istream &input, std::ostream &output) { best = std::max(simulate(program, phases), best); } while (std::next_permutation(phases.begin(), phases.end())); - output << best << std::endl; + output << best << std::endl; } void aoc2019::day07_part2(std::istream &input, std::ostream &output) { - output << "Not implemented\n"; + const auto program = aoc2019::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/tests/samples/07-2-1.in b/2019/tests/samples/07-2-1.in new file mode 100644 index 0000000..3778360 --- /dev/null +++ b/2019/tests/samples/07-2-1.in @@ -0,0 +1,2 @@ +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 new file mode 100644 index 0000000..76bf43f --- /dev/null +++ b/2019/tests/samples/07-2-1.out @@ -0,0 +1 @@ +139629729 diff --git a/2019/tests/samples/07-2-2.in b/2019/tests/samples/07-2-2.in new file mode 100644 index 0000000..6aa329f --- /dev/null +++ b/2019/tests/samples/07-2-2.in @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000..1c14ce2 --- /dev/null +++ b/2019/tests/samples/07-2-2.out @@ -0,0 +1 @@ +18216