Add solution for "Day 24: Crossed Wires", part 1
This commit is contained in:
160
src/CrossedWires.cpp
Normal file
160
src/CrossedWires.cpp
Normal 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 });
|
||||
}
|
||||
@@ -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
45
src/common/LogicGate.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user