From fb8121b093efacac1f19ebae6c0f2bc4136a587b Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 8 Dec 2023 08:37:39 +0000 Subject: [PATCH] 2023 Day 8 --- 2023/puzzle-08-01.cc | 83 +++++++++++++++++++++++++++ 2023/puzzle-08-02.cc | 134 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 2023/puzzle-08-01.cc create mode 100644 2023/puzzle-08-02.cc diff --git a/2023/puzzle-08-01.cc b/2023/puzzle-08-01.cc new file mode 100644 index 0000000..aded7f1 --- /dev/null +++ b/2023/puzzle-08-01.cc @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using UInt = std::uint64_t; +using Location = std::array; +using LocationPair = std::pair; + +auto operator<<(std::ostream& os, Location const& cards) -> std::ostream& +{ + for (auto const c : cards) { os << c; } + return os; +} + +[[nodiscard]] auto operator<=>(Location const& lhs, Location const& rhs) -> std::strong_ordering +{ + for (auto lhs_it{lhs.begin()}, rhs_it{rhs.begin()}; lhs_it != lhs.end(); ++lhs_it, ++rhs_it) { + if (*lhs_it != *rhs_it) { + return *lhs_it <=> *rhs_it; + } + } + return std::strong_ordering::equal; +} + +struct LocationMap +{ + void emplace(std::string_view const line) + { + auto from = Location{line[0], line[1], line[2]}; + auto left = Location{line[7], line[8], line[9]}; + auto right = Location{line[12], line[13], line[14]}; + auto [it, success] = locs_.insert({from, {left, right}}); + assert(success); + } + + std::map locs_; +}; + +auto main() -> int try { + std::string line; + std::string directions; + LocationMap map; + + std::getline(std::cin, directions); /// Directions line + std::getline(std::cin, line); /// Blank line + + while (std::getline(std::cin, line)) { + map.emplace(line); + } + + UInt steps = 0; + auto location = map.locs_.find({'A', 'A', 'A'}); + auto direction = directions.begin(); + while (location->first != Location{'Z', 'Z', 'Z'}) { + if (*direction == 'L') { + location = map.locs_.find(location->second.first); + } + else if (*direction == 'R') { + location = map.locs_.find(location->second.second); + } + else { + std::abort(); + } + ++direction; + if (direction == directions.end()) { direction = directions.begin(); } + ++steps; + } + + std::cout << "Steps: " << steps; + + return EXIT_SUCCESS; +} +catch (...) { + std::cerr << "Uncaught exception.\n"; + return EXIT_FAILURE; +} diff --git a/2023/puzzle-08-02.cc b/2023/puzzle-08-02.cc new file mode 100644 index 0000000..c8926bc --- /dev/null +++ b/2023/puzzle-08-02.cc @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using UInt = std::uint64_t; +using Location = std::array; +using LocationPair = std::pair; + +auto operator<<(std::ostream& os, Location const& cards) -> std::ostream& +{ + for (auto const c : cards) { os << c; } + return os; +} + +[[nodiscard]] auto operator<=>(Location const& lhs, Location const& rhs) -> std::strong_ordering +{ + for (auto lhs_it{lhs.begin()}, rhs_it{rhs.begin()}; lhs_it != lhs.end(); ++lhs_it, ++rhs_it) { + if (*lhs_it != *rhs_it) { + return *lhs_it <=> *rhs_it; + } + } + return std::strong_ordering::equal; +} + +struct LocationMap +{ + void emplace(std::string_view const line) + { + auto from = Location{line[0], line[1], line[2]}; + auto left = Location{line[7], line[8], line[9]}; + auto right = Location{line[12], line[13], line[14]}; + auto [it, success] = locs_.insert({from, {left, right}}); + assert(success); + } + + using const_iterator = std::map::const_iterator; + std::map locs_; +}; + +auto next_location(LocationMap const& map, LocationMap::const_iterator const loc, + char const d) -> LocationMap::const_iterator +{ + if (d == 'L') { + return map.locs_.find(loc->second.first); + } + if (d == 'R') { + return map.locs_.find(loc->second.second); + } + std::abort(); +} + +auto main() -> int try { + std::string line; + std::string directions; + LocationMap map; + std::vector locations; + + std::getline(std::cin, directions); /// Directions line + std::getline(std::cin, line); /// Blank line + + while (std::getline(std::cin, line)) { + map.emplace(line); + if (line[2] == 'A') { + locations.emplace_back(map.locs_.find({line[0], line[1], line[2]})); + } + } + + UInt total_steps = 0; + UInt total_cycle = 1; + + std::cout << "Start: " << total_steps << " steps and " << total_cycle << " cycle.\n"; + + // Big assumption time. + // Let's assume there's a unique Z for each A and we don't see multiple on the cycle. + for (auto location : locations) { + UInt steps = 0; + auto direction = directions.begin(); + +std::cout << "From: " << location->first; + // How many steps to get to the first '..Z' + while (location->first[2] != 'Z') { + location = next_location(map, location, *direction++); + if (direction == directions.end()) { direction = directions.begin(); } + ++steps; + } + + // Step forward one and start counting how many steps until we return to the 'Z'. + auto z_loc = location; + std::cout << " to: " << z_loc->first << " in " << steps << " steps, cycles in: "; + location = next_location(map, location, *direction++); + if (direction == directions.end()) { direction = directions.begin(); } + UInt cycle = 1; + + while (location->first[2] != 'Z') { + location = next_location(map, location, *direction++); + if (direction == directions.end()) { direction = directions.begin(); } + ++cycle; + } + + // Check we've returned to the same 'Z'. + if (location != z_loc) { std::abort(); } + std::cout << cycle << '\n'; + + while (total_steps != steps) { + if (total_steps < steps) { total_steps += total_cycle; } + else { + assert(steps < total_steps); + { + steps += cycle; + } + } + } + total_cycle = std::lcm(total_cycle, cycle); + std::cout << "Meging: " << total_steps << " steps and " << total_cycle << " cycle.\n"; + + } + + std::cout << "Steps: " << total_steps; + + return EXIT_SUCCESS; +} +catch (...) { + std::cerr << "Uncaught exception.\n"; + return EXIT_FAILURE; +}