128 lines
3.7 KiB
C++
128 lines
3.7 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/KeypadConundrum.hpp>
|
|
|
|
#include <sstream>
|
|
#include <stack>
|
|
|
|
KeypadConundrum::KeypadConundrum()
|
|
: numericKeyboardRobot_{ { { 'A', { 0, 0 } }, { '0', { -1, 0 } }, { '1', { -2, -1 } }, { '2', { -1, -1 } },
|
|
{ '3', { 0, -1 } }, { '4', { -2, -2 } }, { '5', { -1, -2 } }, { '6', { 0, -2 } }, { '7', { -2, -3 } },
|
|
{ '8', { -1, -3 } }, { '9', { 0, -3 } } }, { -2, 0 } },
|
|
directionalKeyboardRobot_{ { { 'A', { 0, 0 } }, { '<', { -2, 1 } }, { '>', { 0, 1 } }, { '^', { -1, 0 } },
|
|
{ 'v', { -1, 1 } } }, { -2, 0 } },
|
|
transformations_{}
|
|
{
|
|
}
|
|
|
|
const std::string KeypadConundrum::getPuzzleName() const
|
|
{
|
|
return "Keypad Conundrum";
|
|
}
|
|
|
|
const int KeypadConundrum::getPuzzleDay() const
|
|
{
|
|
return 21;
|
|
}
|
|
|
|
void KeypadConundrum::processDataLine(const std::string& line)
|
|
{
|
|
KeypadPatternTransformation target{ numericKeyboardRobot_.calcTransformation(line) };
|
|
updateTransformationMap(target);
|
|
|
|
std::istringstream stream{ line };
|
|
int64_t number;
|
|
stream >> number;
|
|
|
|
part1 += number * calcAccumulatedLength(target, getPart1NRobots());
|
|
part2 += number * calcAccumulatedLength(target, getPart2NRobots());
|
|
}
|
|
|
|
void KeypadConundrum::finish()
|
|
{
|
|
}
|
|
|
|
constexpr char KeypadConundrum::getStartPositionChar()
|
|
{
|
|
return 'A';
|
|
}
|
|
|
|
constexpr size_t KeypadConundrum::getPart1NRobots()
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
constexpr size_t KeypadConundrum::getPart2NRobots()
|
|
{
|
|
return 25;
|
|
}
|
|
|
|
void KeypadConundrum::updateTransformationMap(KeypadPatternTransformation& targetTransformation)
|
|
{
|
|
std::stack<KeypadPatternTransformation*> stack{};
|
|
stack.push(&targetTransformation);
|
|
|
|
std::vector<KeypadPatternTransformation*> added{};
|
|
|
|
while (!stack.empty())
|
|
{
|
|
auto transformation = stack.top();
|
|
stack.pop();
|
|
|
|
for (const auto& part : transformation->parts)
|
|
{
|
|
auto it = transformations_.find(part);
|
|
if (it == transformations_.end())
|
|
{
|
|
const auto emplaceResult =
|
|
transformations_.emplace(part, directionalKeyboardRobot_.calcTransformation(part));
|
|
it = emplaceResult.first;
|
|
stack.push(&it->second);
|
|
added.push_back(&it->second);
|
|
}
|
|
transformation->partPtrs.push_back(&it->second);
|
|
}
|
|
}
|
|
|
|
updateTransformationMapLengths(added);
|
|
}
|
|
|
|
void KeypadConundrum::updateTransformationMapLengths(const std::vector<KeypadPatternTransformation*>& added)
|
|
{
|
|
for (auto& transformation : added)
|
|
{
|
|
transformation->accumulatedLengths.reserve(getPart2NRobots());
|
|
}
|
|
|
|
for (size_t i = 0; i < getPart2NRobots(); i++)
|
|
{
|
|
for (auto& transformation : added)
|
|
{
|
|
transformation->accumulatedLengths.push_back(calcAccumulatedLength(*transformation, i));
|
|
}
|
|
}
|
|
}
|
|
|
|
int64_t KeypadConundrum::calcAccumulatedLength(KeypadPatternTransformation& transformation, const size_t index)
|
|
{
|
|
int64_t n{ transformation.nDuplicates };
|
|
for (const auto& part : transformation.partPtrs)
|
|
{
|
|
n += part->accumulatedLengths[index];
|
|
}
|
|
return n;
|
|
}
|