diff --git a/README.md b/README.md index bc9d28c..b3c15db 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,12 @@ For this puzzle I added a class for [points in two-dimensional space](include/ao My implementation uses an ordering matrix (a two-dimensional boolean array) to track which page combinations are ordered, and then queries that matrix for each ordered combination of pages in a single line. The same matrix can then also be used for a custom sort function for part 2. +### Day 7: Bridge Repair + +:mag_right: Puzzle: , :white_check_mark: Solver: [`BridgeRepair.cpp`](src/BridgeRepair.cpp) + +The algorithm recursively tries the different operators from left to right until all the calibration numbers have been used. Since the result from any of the operator cannot be less than its operands, any branch of the recursion that surpasses the test value can be aborted. + ### Day 10: Hoof It :mag_right: Puzzle: , :white_check_mark: Solver: [`HoofIt.cpp`](src/HoofIt.cpp) diff --git a/include/aoc/BridgeRepair.hpp b/include/aoc/BridgeRepair.hpp new file mode 100644 index 0000000..f30824a --- /dev/null +++ b/include/aoc/BridgeRepair.hpp @@ -0,0 +1,33 @@ +// 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 + +class BridgeRepair + : 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: + bool testCalibration(const long long int testValue, const std::vector>& calibrationNumbers, + const size_t currentIndex, const bool allowConcatenation, const long long int accumulatedTestValue); +}; diff --git a/include/aoc/Math.hpp b/include/aoc/Math.hpp new file mode 100644 index 0000000..ab27ac3 --- /dev/null +++ b/include/aoc/Math.hpp @@ -0,0 +1,22 @@ +// 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 + +class Math +{ +public: + static int ipow(const int base, const int exponent); +}; diff --git a/src/BridgeRepair.cpp b/src/BridgeRepair.cpp new file mode 100644 index 0000000..fd270c8 --- /dev/null +++ b/src/BridgeRepair.cpp @@ -0,0 +1,95 @@ +// 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 + +#include + +const std::string BridgeRepair::getPuzzleName() const +{ + return "Day 7: Bridge Repair"; +} + +const std::string BridgeRepair::getInputFileName() const +{ + return "bridge_repair.txt"; +} + +void BridgeRepair::processDataLine(const std::string& line) +{ + std::istringstream stringStream{ line }; + + long long int testValue; + char colon; + int calibrationNumber; + // Calibration numbers are a pair of an actual calibration number and its precomputed smallest larger power of 10. + // The precomputed numbers are used to facilitate the "concatenate" operator. + std::vector> calibrationNumbers{}; + + stringStream >> testValue >> colon; + while (stringStream >> calibrationNumber) + { + // Skips the precomputation for the first calibration numbers. + int pow10{ 0 }; + if (!calibrationNumbers.empty()) + { + pow10 = Math::ipow(10, static_cast(floor(log10(calibrationNumber))) + 1); + } + calibrationNumbers.push_back({ calibrationNumber, pow10 }); + } + + if (testCalibration(testValue, calibrationNumbers, 1, false, calibrationNumbers[0].first)) + { + part1 += testValue; + part2 += testValue; + } + else if (testCalibration(testValue, calibrationNumbers, 1, true, calibrationNumbers[0].first)) + { + part2 += testValue; + } +} + +void BridgeRepair::finish() +{ +} + +bool BridgeRepair::testCalibration(const long long int testValue, + const std::vector>& calibrationNumbers, const size_t currentIndex, + const bool allowConcatenation, const long long int accumulatedTestValue) +{ + if (testValue >= accumulatedTestValue && currentIndex < calibrationNumbers.size()) + { + size_t nextIndex{ currentIndex + 1 }; + long long int nextCalibrationNumber{ calibrationNumbers[currentIndex].first }; + // Recursively tries the ||, *, and + operators. + if ((allowConcatenation && testCalibration(testValue, calibrationNumbers, nextIndex, allowConcatenation, + accumulatedTestValue * calibrationNumbers[currentIndex].second + calibrationNumbers[currentIndex].first)) || + testCalibration(testValue, calibrationNumbers, nextIndex, allowConcatenation, + accumulatedTestValue * calibrationNumbers[currentIndex].first) || + testCalibration(testValue, calibrationNumbers, nextIndex, allowConcatenation, + accumulatedTestValue + calibrationNumbers[currentIndex].first)) + { + return true; + } + } + else if (testValue == accumulatedTestValue) + { + return true; + } + return false; +} diff --git a/src/Math.cpp b/src/Math.cpp new file mode 100644 index 0000000..a3769b5 --- /dev/null +++ b/src/Math.cpp @@ -0,0 +1,26 @@ +// 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 + +int Math::ipow(const int base, const int exponent) +{ + int result = 1; + for (int i = 1; i <= exponent; i++) + { + result *= base; + } + return result; +} diff --git a/src/Program.cpp b/src/Program.cpp index 0c05857..5978213 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ void Program::runSolvers() runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); + runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index f7a9581..13f491e 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,19 @@ TEST_CASE("[GuardGallivantTests]") } } +TEST_CASE("[BridgeRepairTests]") +{ + TestContext test; + SECTION("FullData") + { + test.run(std::make_unique(), 12839601725877, 149956401519484, test.getInputPaths()); + } + SECTION("ExampleData") + { + test.run(std::make_unique(), 3749, 11387, test.getExampleInputPaths()); + } +} + TEST_CASE("[HoofItTests]") { TestContext test;