diff --git a/CMakeLists.txt b/CMakeLists.txt index 4801ba0..b9361eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,3 +36,6 @@ target_link_libraries(day13 intcode) add_executable(day15 day15.cpp) target_link_libraries(day15 intcode) + +add_executable(day23 day23.cpp) +target_link_libraries(day23 intcode) diff --git a/day15.cpp b/day15.cpp index f47ba7a..386a452 100644 --- a/day15.cpp +++ b/day15.cpp @@ -15,7 +15,7 @@ namespace { using CoordOp = Coord(Coord); CoordOp* const moves[4] {Up, Down, Left, Right}; -auto Interact(Machine & m, ValueType cmd) { +auto Interact(Machine & m, ValueType cmd) -> ValueType { std::get(Step(m)).pos = cmd; return std::get(Step(m)).val; } @@ -54,7 +54,7 @@ auto Explore(Machine m) -> std::map { // Breadth first search of maze finding shortest path to origin // and furthest point in the maze from the airsource. -auto Compute12(std::map world) -> std::pair { +auto Compute(std::map world) -> std::pair { // Find starting coordinate and remove all the walls from the map Coord start {}; for (auto it = world.begin(); it != world.end(); ) { @@ -72,7 +72,7 @@ auto Compute12(std::map world) -> std::pair { !todo.empty(); todo.pop_front()) { - auto && [steps, here] = todo.front(); + auto [steps, here] = todo.front(); if (Coord{0,0} == here) part1 = steps; part2 = steps; @@ -89,7 +89,7 @@ auto Compute12(std::map world) -> std::pair { } // namespace auto main() -> int { - auto [p1,p2] = Compute12(Explore(Machine{ParseStream(std::cin)})); + auto [p1,p2] = Compute(Explore(Machine{ParseStream(std::cin)})); std::cout << "Part 1: " << p1 << std::endl; std::cout << "Part 2: " << p2 << std::endl; } diff --git a/day23.cpp b/day23.cpp new file mode 100644 index 0000000..412ca6c --- /dev/null +++ b/day23.cpp @@ -0,0 +1,96 @@ +#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; +}