This commit is contained in:
Eric Mertens 2022-11-05 03:25:15 -07:00
parent b7527106ba
commit a37baee99e
2 changed files with 70 additions and 39 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
/build /build
/release /release
.*.swp

106
day15.cpp
View File

@ -1,8 +1,10 @@
#include <algorithm>
#include <deque> #include <deque>
#include <iostream> #include <iostream>
#include <set> #include <map>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <vector>
#include <intcode/intcode.hpp> #include <intcode/intcode.hpp>
#include <intcode/Coord.hpp> #include <intcode/Coord.hpp>
@ -10,56 +12,84 @@ using namespace intcode;
namespace { namespace {
std::pair<ValueType, Coord(*)(Coord)> const moves[4] using CoordOp = Coord(Coord);
{{1, Up}, {2, Down}, {3, Left}, {4, Right}}; CoordOp* const moves[4] {Up, Down, Left, Right};
auto Fork(Machine m, ValueType cmd) { auto Interact(Machine & m, ValueType cmd) {
std::get<Input>(Step(m)).pos = cmd; std::get<Input>(Step(m)).pos = cmd;
auto o = std::get<Output>(Step(m)).val; return std::get<Output>(Step(m)).val;
return std::make_pair(o, std::move(m));
} }
auto Compute(Machine machine) { auto CounterCommand(ValueType x) -> ValueType {
Coord const origin {0,0}; return ((x-1)^1)+1;
std::set<Coord> world {origin}; }
std::deque<std::tuple<int, Coord, Machine>> todo // Depth first search of the maze
{{0, origin, std::move(machine)}}; auto Explore(Machine m) -> std::map<Coord, ValueType> {
std::map<Coord, ValueType> world;
std::vector<ValueType> path {0};
Coord here {};
long part1 = -1; for(;;) {
long part2 = -1; while (path.back() < 4) {
path.back()++;
top: auto here_ = moves[path.back() - 1](here);
while (!todo.empty()) { auto [it, success] = world.insert({here_,0});
auto & [steps, loc, m] = todo.front(); if (success && 0 != (it->second = Interact(m, path.back()))) {
part2 = steps; here = here_;
steps++; path.push_back(0);
for (auto&& [cmd, fun] : moves) {
auto loc_ = fun(loc);
if (world.insert(loc_).second) {
auto [o,m_] = Fork(m, cmd);
switch (o) {
case 2:
part1 = steps;
world = {origin};
todo = {{0, origin, std::move(m_)}};
goto top;
case 1:
todo.emplace_back(steps, loc_, std::move(m_));
}
} }
} }
todo.pop_front();
path.pop_back();
if (path.empty()) { break; }
auto rev = CounterCommand(path.back());
here = moves[rev - 1](here);
Interact(m, rev);
} }
return std::make_pair(part1,part2); return world;
}
// 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++;
}
}
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;
part2 = steps;
for (auto fn : moves) {
auto next = fn(here);
if (world.erase(next)) {
todo.emplace_back(steps+1, next);
}
}
}
return {part1, part2};
} }
} // namespace } // namespace
auto main() -> int { auto main() -> int {
auto [part1, part2] = Compute(Machine{ParseStream(std::cin)}); auto [p1,p2] = Compute12(Explore(Machine{ParseStream(std::cin)}));
std::cout << "Part 1: " << part1 << std::endl; std::cout << "Part 1: " << p1 << std::endl;
std::cout << "Part 2: " << part2 << std::endl; std::cout << "Part 2: " << p2 << std::endl;
} }