diff --git a/include/aoc/PlutonianPebbles.hpp b/include/aoc/PlutonianPebbles.hpp new file mode 100644 index 0000000..8399aa3 --- /dev/null +++ b/include/aoc/PlutonianPebbles.hpp @@ -0,0 +1,36 @@ +// 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 . + +#pragma once + +#include +#include + +#include + +class PlutonianPebbles : public Solver +{ +public: + virtual const std::string getPuzzleName() const override; + virtual const std::string getInputFileName() const override; + virtual void processDataLine(const std::string& line) override; + virtual void finish() override; +private: + static constexpr int getNBlinks(); + std::map> blinkMap_{}; + void addPebble(std::map& pebbles, const long long int pebbleNumber, int cardinality); + void addNextBlinkNumbers(const long long int pebbleNumber, std::vector& nextBlinkNumbers); + int getNNextBlinkNumbers(const long long int pebbleNumber) const; +}; diff --git a/src/PlutonianPebbles.cpp b/src/PlutonianPebbles.cpp new file mode 100644 index 0000000..7ee076f --- /dev/null +++ b/src/PlutonianPebbles.cpp @@ -0,0 +1,143 @@ +// 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 "Day 11: Plutonian Pebbles"; +} + +const std::string PlutonianPebbles::getInputFileName() const +{ + return "plutonian_pebbles.txt"; +} + +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 = getNBlinks(); 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); + } + } + + 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()) + { + part1 += nextBlinkNumber.second * getNNextBlinkNumbers(nextBlinkNumber.first); + } + else + { + part1 += nextBlinkNumber.second * hit->second.size(); + } + } +} + +void PlutonianPebbles::finish() +{ +} + +constexpr int PlutonianPebbles::getNBlinks() +{ + return 25; +} + +void PlutonianPebbles::addPebble(std::map& pebbles, const long long int pebbleNumber, + 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; + } +} diff --git a/src/Program.cpp b/src/Program.cpp index 12301be..0c05857 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,5 +1,5 @@ // Solutions to the Advent Of Code 2024. -// Copyright (C) 2024 Stefan Müller +// Copyright (C) 2024-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 @@ -28,6 +28,7 @@ #include #include #include +#include #include void Program::run() @@ -53,6 +54,7 @@ void Program::runSolvers() runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); + runSolver(solverEngine); runSolver(solverEngine); } diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index 85e70a2..75a7e87 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -1,5 +1,5 @@ // Solutions to the Advent Of Code 2024. -// Copyright (C) 2024 Stefan Müller +// Copyright (C) 2024-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 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -118,6 +119,19 @@ TEST_CASE("[HoofItTests]") } } +TEST_CASE("[PlutonianPebblesTests]") +{ + TestContext test; + SECTION("FullData") + { + test.run(std::make_unique(), 220999, 0, test.getInputPaths()); + } + SECTION("ExampleData") + { + test.run(std::make_unique(), 55312, 0, test.getExampleInputPaths()); + } +} + TEST_CASE("[LanPartyTests]") { TestContext test;