From c7881c47b9b4c15571cdd208227bdb76128bbbc4 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Wed, 25 Dec 2019 16:56:51 +0100 Subject: [PATCH] Implement day 20 part 2. --- 2019/src/day20.cpp | 57 ++++++++++++++++++++++++++++++++++- 2019/tests/samples/20-2-2.in | 37 +++++++++++++++++++++++ 2019/tests/samples/20-2-2.out | 1 + 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 2019/tests/samples/20-2-2.in create mode 100644 2019/tests/samples/20-2-2.out diff --git a/2019/src/day20.cpp b/2019/src/day20.cpp index d5d71b1..d8087f6 100644 --- a/2019/src/day20.cpp +++ b/2019/src/day20.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "days.hpp" #include "point.hpp" @@ -156,5 +157,59 @@ void aoc2019::day20_part1(std::istream &input, std::ostream &output) { } void aoc2019::day20_part2(std::istream &input, std::ostream &output) { - output << "Not implemented\n"; + const auto map = read_map(input); + const auto portals = get_portals(map); + + using state_t = std::pair; + + const auto starting_point = std::find_if(portals.begin(), portals.end(), [](auto &x) { + return x.second == "AA"; + })->first; + + auto graph = get_implicit_graph(map, portals); + + std::set visited; + std::priority_queue, std::vector>, std::greater<>> todo; + todo.emplace(0, 0, starting_point); + + const int outer_x_min = 2; + const int outer_x_max = map[0].size() - 3; + const int outer_y_min = 2; + const int outer_y_max = map.size() - 3; + + while (!todo.empty()) { + const auto[dist, level, pos] = todo.top(); + todo.pop(); + + if (visited.count({level, pos})) { + continue; + } + + visited.emplace(level, pos); + + if (level == 0 && portals.at(pos) == "ZZ") { + output << dist << std::endl; + return; + } + + for (auto &edge : graph[pos]) { + int mod = 0; + if (edge.first == 1) { + // Taking a portal, determine which level we're going to + if (pos[0] == outer_x_max || pos[0] == outer_x_min || pos[1] == outer_y_max || pos[1] == outer_y_min) { + mod = -1; + } else { + mod = 1; + } + } + + if (level + mod < 0 || visited.count({level + mod, edge.second})) { + continue; + } + + todo.emplace(dist + edge.first, level + mod, edge.second); + } + } + + throw std::domain_error("No valid route."); } diff --git a/2019/tests/samples/20-2-2.in b/2019/tests/samples/20-2-2.in new file mode 100644 index 0000000..d051133 --- /dev/null +++ b/2019/tests/samples/20-2-2.in @@ -0,0 +1,37 @@ + Z L X W C + Z P Q B K + ###########.#.#.#.#######.############### + #...#.......#.#.......#.#.......#.#.#...# + ###.#.#.#.#.#.#.#.###.#.#.#######.#.#.### + #.#...#.#.#...#.#.#...#...#...#.#.......# + #.###.#######.###.###.#.###.###.#.####### + #...#.......#.#...#...#.............#...# + #.#########.#######.#.#######.#######.### + #...#.# F R I Z #.#.#.# + #.###.# D E C H #.#.#.# + #.#...# #...#.# + #.###.# #.###.# + #.#....OA WB..#.#..ZH + #.###.# #.#.#.# +CJ......# #.....# + ####### ####### + #.#....CK #......IC + #.###.# #.###.# + #.....# #...#.# + ###.### #.#.#.# +XF....#.# RF..#.#.# + #####.# ####### + #......CJ NM..#...# + ###.#.# #.###.# +RE....#.# #......RF + ###.### X X L #.#.#.# + #.....# F Q P #.#.#.# + ###.###########.###.#######.#########.### + #.....#...#.....#.......#...#.....#.#...# + #####.#.###.#######.#######.###.###.#.#.# + #.......#.......#.#.#.#.#...#...#...#.#.# + #####.###.#####.#.#.#.#.###.###.#.###.### + #.......#.....#.#...#...............#...# + #############.#.#.###.################### + A O F N + A A D M diff --git a/2019/tests/samples/20-2-2.out b/2019/tests/samples/20-2-2.out new file mode 100644 index 0000000..4391a33 --- /dev/null +++ b/2019/tests/samples/20-2-2.out @@ -0,0 +1 @@ +396