Add solution for "Day 24: Crossed Wires", part 1

This commit is contained in:
2025-06-26 20:41:18 +02:00
parent 958adde4a2
commit 4788a1b5ab
8 changed files with 309 additions and 0 deletions

160
src/CrossedWires.cpp Normal file
View File

@@ -0,0 +1,160 @@
// 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/CrossedWires.hpp>
#include <sstream>
CrossedWires::CrossedWires(const int inputFileNameSuffix)
: Solver(inputFileNameSuffix), isProcessingInputWires_{ true }, wires_{}, unevaluatedGates_{}, z_{ 0 }
{
}
const std::string CrossedWires::getPuzzleName() const
{
return "Crossed Wires";
}
const int CrossedWires::getPuzzleDay() const
{
return 24;
}
void CrossedWires::processDataLine(const std::string& line)
{
if (isProcessingInputWires_)
{
if (line.empty())
{
isProcessingInputWires_ = false;
}
else
{
processInputWire(line);
}
}
else
{
processLogicGate(line);
}
}
void CrossedWires::finish()
{
while (!unevaluatedGates_.empty())
{
unevaluatedGates_.remove_if([this](const LogicGate& gate) { return tryEvaluateLogicGate(gate); });
}
part1 = z_.to_ullong();
}
constexpr char CrossedWires::getInputWireDelimiter()
{
return ':';
}
constexpr char CrossedWires::getOutputWiresChar()
{
return 'z';
}
void CrossedWires::processInputWire(const std::string& line)
{
std::istringstream stream{ line };
std::string wire;
int value;
std::getline(stream, wire, getInputWireDelimiter());
stream >> value;
wires_.insert({ wire, value == 1 });
}
void CrossedWires::processLogicGate(const std::string& line)
{
std::istringstream stream{ line };
LogicGate gate;
stream >> gate;
if (!tryEvaluateLogicGate(gate))
{
unevaluatedGates_.push_front(gate);
}
}
bool CrossedWires::tryEvaluateLogicGate(const LogicGate& gate)
{
auto in1 = wires_.find(gate.inputWire1);
if (in1 != wires_.end())
{
if (in1->second)
{
if (gate.kind == LogicGate::Kind::Or)
{
setOutputWire(gate.outputWire, true);
return true;
}
}
else if (gate.kind == LogicGate::Kind::And)
{
setOutputWire(gate.outputWire, false);
return true;
}
}
auto in2 = wires_.find(gate.inputWire2);
if (in2 != wires_.end())
{
if (in2->second)
{
if (gate.kind == LogicGate::Kind::Or)
{
setOutputWire(gate.outputWire, true);
return true;
}
}
else if (gate.kind == LogicGate::Kind::And)
{
setOutputWire(gate.outputWire, false);
return true;
}
if (in1 != wires_.end())
{
switch (gate.kind)
{
case LogicGate ::Kind ::And :
setOutputWire(gate.outputWire, true);
return true;
case LogicGate ::Kind ::Or :
setOutputWire(gate.outputWire, false);
return true;
case LogicGate ::Kind ::Xor :
setOutputWire(gate.outputWire, in1->second != in2->second);
return true;
}
}
}
return false;
}
void CrossedWires::setOutputWire(const std::string& wire, const bool value)
{
if (wire[0] == getOutputWiresChar())
{
size_t index = std::stoull(wire.substr(1, 2));
z_[index] = value;
}
wires_.insert({ wire, value });
}

View File

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

45
src/common/LogicGate.cpp Normal file
View File

@@ -0,0 +1,45 @@
// 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/common/LogicGate.hpp>
std::istream& operator>>(std::istream& is, LogicGate& logicGate)
{
std::string token;
is >> logicGate.inputWire1 >> logicGate.kind >> logicGate.inputWire2 >> token >> logicGate.outputWire;
return is;
}
std::istream& operator>>(std::istream& is, LogicGate::Kind& kind)
{
std::string s;
is >> s;
switch (s[0])
{
case 'A' :
kind = LogicGate::Kind::And;
break;
case 'O' :
kind = LogicGate::Kind::Or;
break;
case 'X' :
kind = LogicGate::Kind::Xor;
break;
default :
kind = LogicGate::Kind::Unknown;
break;
}
return is;
}