// Solutions to the Advent Of Code 2024. // Copyright (C) 2025 Stefan Müller // // This program is free software: you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation, either version 3 of the License, or (at your option) any later // version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . #include #include #include const std::string PlutonianPebbles::getPuzzleName() const { return "Plutonian Pebbles"; } const int PlutonianPebbles::getPuzzleDay() const { return 11; } void PlutonianPebbles::processDataLine(const std::string& line) { // Maps pebble numbers before the blink to their cardinality. auto currentPebbles = std::make_shared>(); // Maps pebble numbers after the blink to their cardinality. std::shared_ptr> nextBlinkPebbles; // Adds initial pebbles numbers. std::istringstream lineStream{ line }; long long int pebbleNumber; while (lineStream >> pebbleNumber) { addPebble(*currentPebbles, pebbleNumber, 1); } // Processes the blinks. for (int i = getNBlinksPart2(); i > 1; i--) { // Maps pebble numbers after the blink to their cardinality. nextBlinkPebbles = std::make_shared>(); for (const auto& pebble : *currentPebbles) { // Finds or inserts the pebble number to the blink map. const auto [it, success] = blinkMap_.insert({ pebble.first, {} }); if (success) { addNextBlinkNumbers(pebble.first, it->second); } // Adds the new pebble numbers to the line. for (const auto nextBlinkNumber : it->second) { addPebble(*nextBlinkPebbles, nextBlinkNumber, pebble.second); } } if (i == getNBlinksPart2() - getNBlinksPart1() + 1) { for (const auto& blinkNumber : *currentPebbles) { // The number is guaranteed to be in blinkMap_ already. auto hit = blinkMap_.find(blinkNumber.first); part1 += blinkNumber.second * hit->second.size(); } } currentPebbles = nextBlinkPebbles; } for (const auto& nextBlinkNumber : *nextBlinkPebbles) { // In the last step we only care about cardinalities, not the actual new pebble numbers, so we use // getNNextBlinkNumbers() instead of addNextBlinkNumbers(). auto hit = blinkMap_.find(nextBlinkNumber.first); if (hit == blinkMap_.end()) { part2 += nextBlinkNumber.second * getNNextBlinkNumbers(nextBlinkNumber.first); } else { part2 += nextBlinkNumber.second * hit->second.size(); } } } void PlutonianPebbles::finish() { } constexpr int PlutonianPebbles::getNBlinksPart1() { return 25; } constexpr int PlutonianPebbles::getNBlinksPart2() { return 75; } void PlutonianPebbles::addPebble(std::map& pebbles, const long long int pebbleNumber, long long int cardinality) { auto hit = pebbles.find(pebbleNumber); if (hit == pebbles.end()) { pebbles.insert({ pebbleNumber, cardinality }); } else { hit->second += cardinality; } } void PlutonianPebbles::addNextBlinkNumbers(const long long int pebbleNumber, std::vector& nextBlinkNumbers) { if (pebbleNumber == 0) { nextBlinkNumbers.push_back(1); } else { auto s = std::to_string(pebbleNumber); if (s.size() % 2 == 0) { auto half = s.size() / 2; nextBlinkNumbers.push_back(std::stoll(s.substr(0, half))); nextBlinkNumbers.push_back(std::stoll(s.substr(half, half))); } else { nextBlinkNumbers.push_back(pebbleNumber * 2024); } } } int PlutonianPebbles::getNNextBlinkNumbers(const long long int pebbleNumber) const { auto s = std::to_string(pebbleNumber); if (s.size() % 2 == 0) { return 2; } else { return 1; } }