96 lines
3.3 KiB
C++
96 lines
3.3 KiB
C++
// 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 "Bridge Repair";
|
|
}
|
|
|
|
const int BridgeRepair::getPuzzleDay() const
|
|
{
|
|
return 7;
|
|
}
|
|
|
|
void BridgeRepair::processDataLine(const std::string& line)
|
|
{
|
|
std::istringstream stream{ 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{};
|
|
|
|
stream >> testValue >> colon;
|
|
while (stream >> 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;
|
|
}
|