#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); StepInput(machines.back(), i); } return machines; } auto Interact(Ethernet & ethernet, Machine & m, std::optional 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 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; }