2022-11-05 03:25:15 -07:00
|
|
|
#include <algorithm>
|
2022-11-27 11:43:10 -08:00
|
|
|
#include <queue>
|
2022-11-03 21:41:06 -07:00
|
|
|
#include <iostream>
|
2022-11-05 03:25:15 -07:00
|
|
|
#include <map>
|
2022-11-03 21:41:06 -07:00
|
|
|
#include <tuple>
|
2022-11-04 17:39:35 -07:00
|
|
|
#include <utility>
|
2022-11-05 03:25:15 -07:00
|
|
|
#include <vector>
|
2022-11-03 21:41:06 -07:00
|
|
|
|
2022-11-06 21:12:30 -08:00
|
|
|
#include <aocpp/Coord.hpp>
|
|
|
|
#include <aocpp/Startup.hpp>
|
2022-11-04 09:38:01 -07:00
|
|
|
#include <intcode/intcode.hpp>
|
2022-11-06 21:12:30 -08:00
|
|
|
using namespace aocpp;
|
2022-11-03 21:41:06 -07:00
|
|
|
using namespace intcode;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2022-11-05 03:25:15 -07:00
|
|
|
using CoordOp = Coord(Coord);
|
|
|
|
CoordOp* const moves[4] {Up, Down, Left, Right};
|
2022-11-03 21:41:06 -07:00
|
|
|
|
2022-11-05 11:19:32 -07:00
|
|
|
auto Interact(Machine & m, ValueType cmd) -> ValueType {
|
2022-11-05 15:06:54 -07:00
|
|
|
StepInput(m, cmd);
|
|
|
|
return StepOutput(m);
|
2022-11-04 17:39:35 -07:00
|
|
|
}
|
2022-11-03 21:41:06 -07:00
|
|
|
|
2022-11-05 03:25:15 -07:00
|
|
|
auto CounterCommand(ValueType x) -> ValueType {
|
|
|
|
return ((x-1)^1)+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Depth first search of the maze
|
|
|
|
auto Explore(Machine m) -> std::map<Coord, ValueType> {
|
|
|
|
std::map<Coord, ValueType> world;
|
|
|
|
std::vector<ValueType> 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);
|
|
|
|
}
|
2022-11-03 21:41:06 -07:00
|
|
|
|
2022-11-05 03:25:15 -07:00
|
|
|
return world;
|
|
|
|
}
|
2022-11-04 11:37:32 -07:00
|
|
|
|
2022-11-05 03:25:15 -07:00
|
|
|
// Breadth first search of maze finding shortest path to origin
|
|
|
|
// and furthest point in the maze from the airsource.
|
2022-11-05 11:19:32 -07:00
|
|
|
auto Compute(std::map<Coord, ValueType> world) -> std::pair<int, int> {
|
2022-11-05 03:25:15 -07:00
|
|
|
// 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++;
|
|
|
|
}
|
|
|
|
}
|
2022-11-04 17:39:35 -07:00
|
|
|
|
2022-11-05 03:25:15 -07:00
|
|
|
int part1 = -1;
|
|
|
|
int part2 = -1;
|
|
|
|
|
2022-11-27 11:43:10 -08:00
|
|
|
for (
|
|
|
|
std::queue<std::pair<int, Coord>> todo
|
|
|
|
{decltype(todo)::container_type{{0,start}}};
|
|
|
|
!todo.empty();
|
|
|
|
todo.pop())
|
2022-11-05 03:25:15 -07:00
|
|
|
{
|
2022-11-05 11:19:32 -07:00
|
|
|
auto [steps, here] = todo.front();
|
2022-11-05 03:25:15 -07:00
|
|
|
if (Coord{0,0} == here) part1 = steps;
|
2022-11-04 17:39:35 -07:00
|
|
|
part2 = steps;
|
2022-11-05 03:25:15 -07:00
|
|
|
|
|
|
|
for (auto fn : moves) {
|
|
|
|
auto next = fn(here);
|
|
|
|
if (world.erase(next)) {
|
2022-11-27 11:43:10 -08:00
|
|
|
todo.emplace(steps+1, next);
|
2022-11-04 08:29:02 -07:00
|
|
|
}
|
2022-11-03 21:41:06 -07:00
|
|
|
}
|
2022-11-04 08:29:02 -07:00
|
|
|
}
|
2022-11-05 03:25:15 -07:00
|
|
|
return {part1, part2};
|
2022-11-03 21:41:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2023-01-31 09:15:15 -08:00
|
|
|
auto Main(std::istream & in, std::ostream & out) -> void
|
2023-01-31 08:58:42 -08:00
|
|
|
{
|
|
|
|
auto const [p1,p2] = Compute(Explore(Machine{ParseStream(in)}));
|
2023-01-31 09:15:15 -08:00
|
|
|
out << "Part 1: " << p1 << std::endl;
|
|
|
|
out << "Part 2: " << p2 << std::endl;
|
2022-11-03 21:41:06 -07:00
|
|
|
}
|