#include #include #include #include #include #include #include #include #include #include using namespace intcode; namespace { using Packet = std::pair; using Ethernet = std::deque>; auto BuildNetwork(Machine m) -> std::vector { std::vector machines; for (int i = 0; i < 50; i++) { machines.push_back(m); std::get(Step(machines.back())).pos = i; } return machines; } auto Interact(Ethernet & ethernet, Machine & m, std::optional p) -> void { for(;;) { auto effect = Step(m); switch (effect.index()) { default: throw std::runtime_error{"unexpected halt"}; case 0: // Input if (p) { std::get(effect).pos = p->first; std::get(Step(m)).pos = p->second; p = {}; break; } std::get(effect).pos = -1; // no packet return; case 1: // Output auto d = std::get(effect).val; auto x = std::get(Step(m)).val; auto y = std::get(Step(m)).val; ethernet.push_back({d, {x,y}}); break; } } } } // namespace auto main(int argc, char ** argv) -> int { if (2 != argc) { return 1; } std::ifstream fin {argv[1]}; auto machines = BuildNetwork(Machine{ParseStream(fin)}); auto ethernet = Ethernet{}; std::optional part1; std::optional part2; std::optional 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; }