90 lines
2.0 KiB
C++
90 lines
2.0 KiB
C++
#include <cstddef>
|
|
#include <deque>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <tuple>
|
|
#include <utility>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
#include <intcode/intcode.hpp>
|
|
using namespace intcode;
|
|
|
|
namespace {
|
|
|
|
using Packet = std::pair<ValueType, ValueType>;
|
|
using Ethernet = std::deque<std::pair<std::size_t, Packet>>;
|
|
|
|
auto BuildNetwork(Machine m) -> std::vector<Machine> {
|
|
std::vector<Machine> machines;
|
|
for (int i = 0; i < 50; i++) {
|
|
machines.push_back(m);
|
|
StepInput(machines.back(), i);
|
|
}
|
|
return machines;
|
|
}
|
|
|
|
auto Interact(Ethernet & ethernet, Machine & m, std::optional<Packet> p) -> void {
|
|
while(std::visit(overloaded{
|
|
|
|
[&](Input i) {
|
|
if (p) {
|
|
i.pos = p->first;
|
|
StepInput(m, p->second);
|
|
p = {};
|
|
return true;
|
|
}
|
|
i.pos = -1; // no packet
|
|
return false;
|
|
},
|
|
|
|
[&](Output o) {
|
|
auto x = StepOutput(m);
|
|
auto y = StepOutput(m);
|
|
ethernet.push_back({o.val, {x,y}});
|
|
return true;
|
|
},
|
|
|
|
[](Halt) -> bool { throw std::runtime_error{"unexpected halt"}; },
|
|
}, Step(m))) {}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
auto main() -> int {
|
|
auto machines = BuildNetwork(Machine{ParseStream(std::cin)});
|
|
auto ethernet = Ethernet{};
|
|
|
|
std::optional<ValueType> part1;
|
|
std::optional<ValueType> part2;
|
|
std::optional<Packet> nat;
|
|
|
|
for(;;) {
|
|
if (ethernet.empty()) {
|
|
if (nat) {
|
|
if (nat->second == part2) { break; }
|
|
part2 = nat->second;
|
|
Interact(ethernet, machines[0], nat);
|
|
} else {
|
|
for (auto && m : machines) {
|
|
Interact(ethernet, m, {});
|
|
}
|
|
}
|
|
} else {
|
|
auto [dest, p] = ethernet.front();
|
|
ethernet.pop_front();
|
|
if (dest == 255) {
|
|
nat = p;
|
|
if (!part1) { part1 = p.second; }
|
|
} else if (dest < 50) {
|
|
Interact(ethernet, machines[dest], p);
|
|
} else {
|
|
throw std::runtime_error{"bad destination"};
|
|
}
|
|
}
|
|
}
|
|
|
|
std::cout << "Part 1: " << *part1 << std::endl;
|
|
std::cout << "Part 2: " << *part2 << std::endl;
|
|
}
|