#include #include #include #include #include #include #include #include #include #include using aocpp::Coord; using aocpp::Grid; namespace { auto Parse(std::istream & in) -> std::tuple { Coord start {}; Coord end {}; auto grid = Grid::Parse(in); grid.each([&](Coord c, char v) { switch (v) { case 'S': grid[c] = 'a'; start = c; break; case 'E': grid[c] = 'z'; end = c; break; } }); return {start, end, std::move(grid)}; } auto Solve(std::vector starts, Coord end, Grid const& grid) -> std::int64_t { std::vector prev_layer(std::move(starts)); std::vector next_layer; std::set seen; std::int64_t counter {1}; while (!prev_layer.empty()) { for (auto here : prev_layer) { if (!seen.insert(here).second) continue; auto here_height = grid[here]; for (auto next : {Up(here), Down(here), Left(here), Right(here)}) { if (!grid.contains(next)) continue; if (grid[next] - here_height > 1) continue; if (next == end) { return counter; } next_layer.push_back(next); } } counter++; prev_layer.clear(); std::swap(prev_layer, next_layer); } return -1; } auto Part2Starts(Grid const& grid) -> std::vector { std::vector starts; grid.each([&](Coord c, char v) { if (v == 'a') starts.push_back(c); }); return starts; } } // namespace TEST_SUITE("2022-12 examples") { TEST_CASE("documented example") { std::istringstream in { "Sabqponm\n" "abcryxxl\n" "accszExk\n" "acctuvwj\n" "abdefghi\n" }; auto [start, end, grid] = Parse(in); CHECK(31 == Solve({start}, end, grid)); CHECK(29 == Solve(Part2Starts(grid), end, grid)); } } auto main(int argc, char** argv) -> int { auto [start, end, grid] = Parse(*aocpp::Startup(argc, argv)); std::cout << "Part 1: " << Solve({start}, end, grid) << std::endl; std::cout << "Part 2: " << Solve(Part2Starts(grid), end, grid) << std::endl; }