From 262c339920b071d2e6515390ba13ddace7c9cd84 Mon Sep 17 00:00:00 2001 From: Eric Mertens Date: Thu, 10 Nov 2022 11:11:02 -0800 Subject: [PATCH] 18 --- 2019/18.cpp | 56 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/2019/18.cpp b/2019/18.cpp index 05f6d74..7274495 100644 --- a/2019/18.cpp +++ b/2019/18.cpp @@ -94,7 +94,7 @@ auto FindDistances(Map const& map, Features const& features) -> Distances { Distances distances; for (auto && [start_letter, start_coord] : features) { - if (islower(start_letter) || start_letter == '@') { + if (!std::isupper(start_letter)) { FindDistancesFrom(map, features, distances, start_letter, start_coord); } } @@ -102,12 +102,6 @@ auto FindDistances(Map const& map, Features const& features) -> Distances { return distances; } -struct P1S { - char location; - unsigned long long keys; - auto operator<=>(P1S const&) const = default; -}; - auto HasKey(Doors doors, char key) { return doors.test(std::toupper(key) - 'A'); } @@ -116,26 +110,31 @@ auto SetKey(Doors doors, char key) { return doors.set(std::toupper(key) - 'A'); } -auto Part1(Distances const& distances) -> std::int64_t { - std::set seen; - std::multimap> todo - {{0, {'@', Doors()}}}; +auto SolveMaze(Distances const& distances, std::set const initial_locations) -> std::int64_t { + // Track current positions and current set of keys in easy to compare form + using Visited = std::pair, unsigned long long>; + std::set seen; + + std::multimap, Doors>> todo + {{0, {initial_locations, Doors()}}}; while (!todo.empty()) { auto it = todo.begin(); auto [steps, ld] = *it; - auto& [l,keys] = ld; + auto& [locations,keys] = ld; todo.erase(it); if (keys.all()) { return steps; } - if (seen.insert({l,keys.to_ullong()}).second) { - auto dit = distances.find(l); - if (dit != distances.end()) { - for (auto && [next, costneed] : dit->second) { + if (seen.insert({locations,keys.to_ullong()}).second) { + for (auto location : locations) { + auto locations1 = locations; locations1.erase(location); + + for (auto && [next, costneed] : distances.at(location)) { auto [cost, need] = costneed; - if ((need & (~keys)).none()) { - todo.insert({steps + cost, {next, SetKey(keys, next)}}); + if ((need & ~keys).none()) { + auto locations2 = locations1; locations2.insert(next); + todo.insert({steps + cost, {locations2, SetKey(keys, next)}}); } } } @@ -145,6 +144,20 @@ auto Part1(Distances const& distances) -> std::int64_t { throw std::runtime_error{"no solution to part 1"}; } +auto UpdateMap(Map& map, Features & features) { + auto start = features['@']; + map[start.y][start.x] = '#'; + map[start.y][start.x+1] = '#'; + map[start.y][start.x-1] = '#'; + map[start.y+1][start.x] = '#'; + map[start.y-1][start.x] = '#'; + features.erase('@'); + features['^'] = Up(Left(start)); + features['&'] = Down(Left(start)); + features['*'] = Up(Right(start)); + features['$'] = Down(Right(start)); +} + } // namespace auto main(int argc, char** argv) -> int { @@ -152,6 +165,9 @@ auto main(int argc, char** argv) -> int { auto features = FindFeatures(map); auto distances = FindDistances(map, features); - std::cout << "Part 1: " << Part1(distances) << std::endl; - //std::cout << "Part 2: " << part2 << std::endl; + std::cout << "Part 1: " << SolveMaze(distances, {'@'}) << std::endl; + + UpdateMap(map, features); + distances = FindDistances(map, features); + std::cout << "Part 2: " << SolveMaze(distances, {'^', '&', '*', '$'}) << std::endl; }