Add solution for "Day 25: Code Chronicle"
This commit is contained in:
parent
37d60d01ed
commit
0113dc579e
@ -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.
|
||||
|
44
include/aoc/CodeChronicle.hpp
Normal file
44
include/aoc/CodeChronicle.hpp
Normal 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
101
src/CodeChronicle.cpp
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user