From a37baee99e6a398a784d1daf00e63132eda49928 Mon Sep 17 00:00:00 2001 From: Eric Mertens Date: Sat, 5 Nov 2022 03:25:15 -0700 Subject: [PATCH] 15 --- .gitignore | 3 +- day15.cpp | 106 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 956c004..2b3d866 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /build -/release \ No newline at end of file +/release +.*.swp diff --git a/day15.cpp b/day15.cpp index 6877204..f47ba7a 100644 --- a/day15.cpp +++ b/day15.cpp @@ -1,8 +1,10 @@ +#include #include #include -#include +#include #include #include +#include #include #include @@ -10,56 +12,84 @@ using namespace intcode; namespace { -std::pair const moves[4] - {{1, Up}, {2, Down}, {3, Left}, {4, Right}}; +using CoordOp = Coord(Coord); +CoordOp* const moves[4] {Up, Down, Left, Right}; -auto Fork(Machine m, ValueType cmd) { +auto Interact(Machine & m, ValueType cmd) { std::get(Step(m)).pos = cmd; - auto o = std::get(Step(m)).val; - return std::make_pair(o, std::move(m)); + return std::get(Step(m)).val; } -auto Compute(Machine machine) { - Coord const origin {0,0}; - std::set world {origin}; +auto CounterCommand(ValueType x) -> ValueType { + return ((x-1)^1)+1; +} - std::deque> todo - {{0, origin, std::move(machine)}}; +// Depth first search of the maze +auto Explore(Machine m) -> std::map { + std::map world; + std::vector path {0}; + Coord here {}; - long part1 = -1; - long part2 = -1; - -top: - while (!todo.empty()) { - auto & [steps, loc, m] = todo.front(); - part2 = steps; - steps++; - - 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_)); - } + 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); } } - 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 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::deque> 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 auto main() -> int { - auto [part1, part2] = Compute(Machine{ParseStream(std::cin)}); - std::cout << "Part 1: " << part1 << std::endl; - std::cout << "Part 2: " << part2 << std::endl; + auto [p1,p2] = Compute12(Explore(Machine{ParseStream(std::cin)})); + std::cout << "Part 1: " << p1 << std::endl; + std::cout << "Part 2: " << p2 << std::endl; }