Add solutions for "Day 7: Bridge Repair"

This commit is contained in:
Stefan Müller 2025-01-29 09:38:01 +01:00
parent 9bc4c3e6be
commit c4b2684d66
7 changed files with 198 additions and 0 deletions

View File

@ -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: <https://adventofcode.com/2024/day/7>, :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: <https://adventofcode.com/2024/day/10>, :white_check_mark: Solver: [`HoofIt.cpp`](src/HoofIt.cpp)

View File

@ -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 <http://www.gnu.org/licenses/>.
#pragma once
#include <vector>
#include <aoc/Solver.hpp>
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<std::pair<int, int>>& calibrationNumbers,
const size_t currentIndex, const bool allowConcatenation, const long long int accumulatedTestValue);
};

22
include/aoc/Math.hpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
#pragma once
class Math
{
public:
static int ipow(const int base, const int exponent);
};

95
src/BridgeRepair.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
#include <aoc/BridgeRepair.hpp>
#include <cmath>
#include <sstream>
#include <aoc/Math.hpp>
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<std::pair<int, int>> 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<int>(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<std::pair<int, int>>& 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;
}

26
src/Math.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
#include <aoc/Math.hpp>
int Math::ipow(const int base, const int exponent)
{
int result = 1;
for (int i = 1; i <= exponent; i++)
{
result *= base;
}
return result;
}

View File

@ -27,6 +27,7 @@
#include <aoc/CeresSearch.hpp>
#include <aoc/PrintQueue.hpp>
#include <aoc/GuardGallivant.hpp>
#include <aoc/BridgeRepair.hpp>
#include <aoc/HoofIt.hpp>
#include <aoc/PlutonianPebbles.hpp>
#include <aoc/LanParty.hpp>
@ -53,6 +54,7 @@ void Program::runSolvers()
runSolver<CeresSearch>(solverEngine);
runSolver<PrintQueue>(solverEngine);
runSolver<GuardGallivant>(solverEngine);
runSolver<BridgeRepair>(solverEngine);
runSolver<HoofIt>(solverEngine);
runSolver<PlutonianPebbles>(solverEngine);
runSolver<LanParty>(solverEngine);

View File

@ -21,6 +21,7 @@
#include <aoc/CeresSearch.hpp>
#include <aoc/PrintQueue.hpp>
#include <aoc/GuardGallivant.hpp>
#include <aoc/BridgeRepair.hpp>
#include <aoc/HoofIt.hpp>
#include <aoc/PlutonianPebbles.hpp>
#include <aoc/LanParty.hpp>
@ -106,6 +107,19 @@ TEST_CASE("[GuardGallivantTests]")
}
}
TEST_CASE("[BridgeRepairTests]")
{
TestContext test;
SECTION("FullData")
{
test.run(std::make_unique<BridgeRepair>(), 12839601725877, 149956401519484, test.getInputPaths());
}
SECTION("ExampleData")
{
test.run(std::make_unique<BridgeRepair>(), 3749, 11387, test.getExampleInputPaths());
}
}
TEST_CASE("[HoofItTests]")
{
TestContext test;