From fcaf7595dbec8c30d2107b07ac8a9e3ce21c4bc1 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Sun, 12 Dec 2021 08:02:35 +0000 Subject: [PATCH] Add 2021 day 12 puzzles --- 2021/puzzle-12-01.cc | 76 +++++++++++++++++++++++++++++++++++ 2021/puzzle-12-02.cc | 94 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 2021/puzzle-12-01.cc create mode 100644 2021/puzzle-12-02.cc diff --git a/2021/puzzle-12-01.cc b/2021/puzzle-12-01.cc new file mode 100644 index 0000000..46f91c8 --- /dev/null +++ b/2021/puzzle-12-01.cc @@ -0,0 +1,76 @@ +// +// Created by Matthew Gretton-Dann on 12/12/2021. +// + +#include +#include +#include +#include +#include + +using Paths = std::multimap; +using Route = std::vector; + +auto is_upper_case(std::string const& s) -> bool { return std::isupper(s[0]) ? true : false; } + +auto is_visitable(Route const& route, Paths const& paths, std::string const& proposed) -> bool +{ + if (is_upper_case(proposed)) { + return true; + } + auto route_it = std::find(route.begin(), route.end(), proposed); + return route_it == route.end(); +} + +template +void visit(Route& route, Paths const& paths, Fn visitor) +{ + auto [path_begin, path_end] = paths.equal_range(route.back()); + if (path_begin == path_end) { + visitor(route, paths); + return; + } + + for (auto it{path_begin}; it != path_end; ++it) { + if (is_visitable(route, paths, it->second)) { + route.push_back(it->second); + visit(route, paths, visitor); + route.pop_back(); + } + } +} + +auto main() -> int +{ + Paths paths; + std::string line; + while (std::getline(std::cin, line)) { + auto sep{line.find('-')}; + auto from{line.substr(0, sep)}; + auto to{line.substr(sep + 1)}; + + // Make sure we don't visit start or end more than once. + if (to == "start") { + std::swap(from, to); + } + if (from == "end") { + std::swap(from, to); + } + paths.insert({from, to}); + if (from != "start" && to != "end") { + paths.insert({to, from}); + } + } + + unsigned route_count{0}; + Route route{"start"}; + visit(route, paths, [&route_count](auto const& route, auto const&) { + for (auto r : route) { + std::cout << " " << r; + } + std::cout << "\n"; + ++route_count; + }); + std::cout << "Routes count: " << route_count; + return 0; +} diff --git a/2021/puzzle-12-02.cc b/2021/puzzle-12-02.cc new file mode 100644 index 0000000..44d1417 --- /dev/null +++ b/2021/puzzle-12-02.cc @@ -0,0 +1,94 @@ +// +// Created by Matthew Gretton-Dann on 12/12/2021. +// + +#include +#include +#include +#include +#include +#include + +using Paths = std::multimap; +using Route = std::vector; + +auto is_upper_case(std::string const& s) -> bool { return std::isupper(s[0]) ? true : false; } + +auto is_visitable(Route const& route, Paths const& paths, std::string const& proposed) -> bool +{ + if (is_upper_case(proposed)) { + return true; + } + + std::set visited; + bool little_visited_twice{false}; + for (auto r : route) { + if (!is_upper_case(r)) { + if (visited.contains(r)) { + little_visited_twice = true; + break; + } + visited.insert(r); + } + } + + if (!little_visited_twice) { + return true; + } + + auto route_it = std::find(route.begin(), route.end(), proposed); + return route_it == route.end(); +} + +template +void visit(Route& route, Paths const& paths, Fn visitor) +{ + auto [path_begin, path_end] = paths.equal_range(route.back()); + if (path_begin == path_end) { + visitor(route, paths); + return; + } + + for (auto it{path_begin}; it != path_end; ++it) { + if (is_visitable(route, paths, it->second)) { + route.push_back(it->second); + visit(route, paths, visitor); + route.pop_back(); + } + } +} + +auto main() -> int +{ + Paths paths; + std::string line; + while (std::getline(std::cin, line)) { + auto sep{line.find('-')}; + auto from{line.substr(0, sep)}; + auto to{line.substr(sep + 1)}; + + // Make sure we don't visit start or end more than once. + if (to == "start") { + std::swap(from, to); + } + if (from == "end") { + std::swap(from, to); + } + paths.insert({from, to}); + if (from != "start" && to != "end") { + paths.insert({to, from}); + } + } + + unsigned route_count{0}; + Route route{"start"}; + visit(route, paths, [&route_count](auto const& route, auto const&) { + for (auto r : route) { + std::cout << " " << r; + } + std::cout << "\n"; + ++route_count; + }); + std::cout << "Routes count: " << route_count; + return 0; +}