Very ugly solution to part 2.

This commit is contained in:
2019-12-07 16:39:41 +01:00
parent 99b42ff04e
commit 0613778036
5 changed files with 167 additions and 6 deletions

View File

@@ -1,23 +1,168 @@
#include <array>
#include <iostream>
#include <memory>
#include "days.hpp"
#include "utils.hpp"
namespace {
int simulate(const std::vector<int>& program, const std::vector<int> phases) {
namespace {
class IntCodeComputer {
public:
explicit IntCodeComputer(std::vector<int> program, std::deque<int> 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<int> &currentInputs() const {
return inputs;
}
private:
std::vector<int> program;
std::deque<int> 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<int> &program, const std::array<int, 5> &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<int> &program, const std::array<int, 5> &phases) {
std::vector<IntCodeComputer> computers;
for (int phase : phases) {
computers.emplace_back(program, std::deque<int>{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<int> phases{0, 1, 2, 3, 4};
std::array<int, 5> 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<int, 5> 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;
}

View File

@@ -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

View File

@@ -0,0 +1 @@
139629729

View File

@@ -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

View File

@@ -0,0 +1 @@
18216