#include #include #include #include #include #include #include #include #include #include using namespace aocpp; using namespace intcode; namespace { using CoordOp = Coord(Coord); CoordOp* const moves[4] {Up, Down, Left, Right}; auto Interact(Machine & m, ValueType cmd) -> ValueType { StepInput(m, cmd); return StepOutput(m); } auto CounterCommand(ValueType x) -> ValueType { return ((x-1)^1)+1; } // Depth first search of the maze auto Explore(Machine m) -> std::map { std::map world; std::vector path {0}; Coord here {}; for(;;) { while (path.back() < 4) { path.back()++; auto here_ = moves[path.back() - 1](here); auto [it, success] = world.insert({here_,0}); if (success && 0 != (it->second = Interact(m, path.back()))) { here = here_; path.push_back(0); } } path.pop_back(); if (path.empty()) { break; } auto rev = CounterCommand(path.back()); here = moves[rev - 1](here); Interact(m, rev); } return world; } // Breadth first search of maze finding shortest path to origin // and furthest point in the maze from the airsource. 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(); ) { switch (it->second) { case 2: start = it->first; case 0: it = world.erase(it); break; default: it++; } } int part1 = -1; int part2 = -1; for ( std::queue> todo {decltype(todo)::container_type{{0,start}}}; !todo.empty(); todo.pop()) { auto [steps, here] = todo.front(); if (Coord{0,0} == here) part1 = steps; part2 = steps; for (auto fn : moves) { auto next = fn(here); if (world.erase(next)) { todo.emplace(steps+1, next); } } } return {part1, part2}; } } // namespace auto Main(std::istream & in, std::ostream & out) -> void { auto const [p1,p2] = Compute(Explore(Machine{ParseStream(in)})); out << "Part 1: " << p1 << std::endl; out << "Part 2: " << p2 << std::endl; }