Add solution for "Day 25: Code Chronicle"

This commit is contained in:
Stefan Müller 2025-07-10 19:42:44 +02:00
parent 37d60d01ed
commit 0113dc579e
5 changed files with 167 additions and 0 deletions

View File

@ -194,6 +194,12 @@ For part 1, many of the output wire values can be determined on the fly, in part
The solver then validates all logic gates against parts of the expected structure of a full adder, comprised out of a certain combination of five logic gates per resulting digit and their linking wires, to find the 8 swapped output wires.
### Day 25: Code Chronicle
:mag_right: Puzzle: <https://adventofcode.com/2024/day/25>, :white_check_mark: Solver: [`CodeChronicle.cpp`](src/CodeChronicle.cpp)
For the last puzzle, the solver translates each key and lock into an array of pin heights as described in the puzzle, and then checks each of these schematics against the list of already parsed locks or keys, respectively. If the sums of all pairs of corresponding pins from a lock and a key are less than five, they fit.
## Thanks
* [Alexander Brouwer](https://github.com/Bromvlieg) for getting the project set up with CMake.

View File

@ -0,0 +1,44 @@
// 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 <array>
#include <vector>
#include <aoc/framework/Solver-types.hpp>
class CodeChronicle
: public Solver<int64_t, int64_t>
{
public:
virtual const std::string getPuzzleName() const override;
virtual const int getPuzzleDay() const override;
virtual void processDataLine(const std::string& line) override;
virtual void finish() override;
private:
using Schematic = std::array<uint32_t, 5>;
static constexpr char getFilledChar();
static constexpr unsigned getSchematicHeight();
bool isNewSchematic_{ true };
bool isLock_{};
Schematic* current_;
std::vector<Schematic> locks_{};
std::vector<Schematic> keys_{};
void resetCurrentSchematic();
void updateCurrentSchematic(const std::string& line);
void finishCurrentSchematic();
bool canFit(const Schematic& schematic1, const Schematic& schematic2);
};

101
src/CodeChronicle.cpp Normal file
View File

@ -0,0 +1,101 @@
// 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/CodeChronicle.hpp>
const std::string CodeChronicle::getPuzzleName() const
{
return "Code Chronicle";
}
const int CodeChronicle::getPuzzleDay() const
{
return 25;
}
void CodeChronicle::processDataLine(const std::string& line)
{
if (line.empty())
{
finishCurrentSchematic();
isNewSchematic_ = true;
}
else if (isNewSchematic_)
{
isNewSchematic_ = false;
isLock_ = (line[0] == getFilledChar());
resetCurrentSchematic();
}
else
{
updateCurrentSchematic(line);
}
}
void CodeChronicle::finish()
{
finishCurrentSchematic();
}
constexpr char CodeChronicle::getFilledChar()
{
return '#';
}
constexpr unsigned CodeChronicle::getSchematicHeight()
{
return 5;
}
void CodeChronicle::resetCurrentSchematic()
{
current_ = &(isLock_ ? locks_ : keys_).emplace_back();
// Sets the current schema to all -1's for keys, to compensate for counting their invariable "#" base line later.
current_->fill(isLock_ ? 0 : -1);
}
void CodeChronicle::updateCurrentSchematic(const std::string& line)
{
for (size_t i = 0; i < line.size(); i++)
{
if (line[i] == getFilledChar())
{
(*current_)[i]++;
}
}
}
void CodeChronicle::finishCurrentSchematic()
{
for (auto& schema : isLock_ ? keys_ : locks_)
{
if (canFit(*current_, schema))
{
part1++;
}
}
}
bool CodeChronicle::canFit(const Schematic& schematic1, const Schematic& schematic2)
{
for (size_t i = 0; i < schematic1.size(); i++)
{
if (schematic1[i] + schematic2[i] > getSchematicHeight())
{
return false;
}
}
return true;
}

View File

@ -45,6 +45,7 @@
#include <aoc/MonkeyMarket.hpp>
#include <aoc/LanParty.hpp>
#include <aoc/CrossedWires.hpp>
#include <aoc/CodeChronicle.hpp>
void Program::run()
{
@ -86,6 +87,7 @@ void Program::runSolvers()
runSolver<MonkeyMarket>(solverEngine);
runSolver<LanParty>(solverEngine);
runSolver<CrossedWires>(solverEngine);
runSolver<CodeChronicle>(solverEngine);
}
std::vector<std::string> Program::getInputPaths() const

View File

@ -42,6 +42,7 @@
#include <aoc/MonkeyMarket.hpp>
#include <aoc/LanParty.hpp>
#include <aoc/CrossedWires.hpp>
#include <aoc/CodeChronicle.hpp>
#define REQUIRE_MESSAGE(cond, msg) if (!(cond)) { INFO(msg); REQUIRE(cond); }
@ -431,3 +432,16 @@ TEST_CASE("[CrossedWiresTests]")
test.runExamplePart1(std::make_unique<CrossedWires>(2), 2024);
}
}
TEST_CASE("[CodeChronicleTests]")
{
TestContext test;
SECTION("FullData")
{
test.runFull(std::make_unique<CodeChronicle>(), 2854, 0);
}
SECTION("ExampleData")
{
test.runExamplePart1(std::make_unique<CodeChronicle>(), 3);
}
}