aocpp/day15.cpp

96 lines
2.2 KiB
C++
Raw Normal View History

2022-11-05 03:25:15 -07:00
#include <algorithm>
2022-11-04 17:39:35 -07:00
#include <deque>
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-04 09:38:01 -07:00
#include <intcode/intcode.hpp>
2022-11-04 21:27:08 -07:00
#include <intcode/Coord.hpp>
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 03:25:15 -07:00
auto Interact(Machine & m, ValueType cmd) {
2022-11-04 17:39:35 -07:00
std::get<Input>(Step(m)).pos = cmd;
2022-11-05 03:25:15 -07:00
return std::get<Output>(Step(m)).val;
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.
auto Compute12(std::map<Coord, ValueType> world) -> std::pair<int, int> {
// 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;
for (std::deque<std::pair<int, Coord>> todo {{0,start}};
!todo.empty();
todo.pop_front())
{
auto && [steps, here] = todo.front();
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)) {
todo.emplace_back(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
auto main() -> int {
2022-11-05 03:25:15 -07:00
auto [p1,p2] = Compute12(Explore(Machine{ParseStream(std::cin)}));
std::cout << "Part 1: " << p1 << std::endl;
std::cout << "Part 2: " << p2 << std::endl;
2022-11-03 21:41:06 -07:00
}