diff --git a/include/aoc/Graph.hpp b/include/aoc/Graph.hpp new file mode 100644 index 0000000..3e5e3c6 --- /dev/null +++ b/include/aoc/Graph.hpp @@ -0,0 +1,32 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2024 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 . + +#pragma once + +#include +#include +#include + +#include + +class Graph +{ +public: + const std::map>& getVertices() const; + void addEdge(const std::string& vertexId1, const std::string& vertexId2); +private: + std::map> vertices_; + std::shared_ptr findOrAddVertex(const std::string& vertexId); +}; diff --git a/include/aoc/LanParty.hpp b/include/aoc/LanParty.hpp new file mode 100644 index 0000000..c06213f --- /dev/null +++ b/include/aoc/LanParty.hpp @@ -0,0 +1,34 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2024 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 . + +#pragma once + +#include +#include + +class LanParty : public Solver +{ +public: + std::string getPuzzleName() const override; + std::string getInputFileName() const override; + void processDataLine(const std::string& line) override; + void finish() override; +private: + Graph lan_; + void countInterconnectedThreeSets(const Vertex& vertexTx); + bool shallProcessVertex(const Vertex& vertexToCheck, const Vertex& vertexTx) const; + const std::string getFirstTxComputerName() const; + const std::string getLastTxComputerName() const; +}; diff --git a/include/aoc/Vertex.hpp b/include/aoc/Vertex.hpp new file mode 100644 index 0000000..35f1b20 --- /dev/null +++ b/include/aoc/Vertex.hpp @@ -0,0 +1,32 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2024 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 . + +#pragma once + +#include +#include +#include + +class Vertex +{ +public: + Vertex(const std::string id); + std::string getId() const; + const std::vector>& getNeighbors() const; + void addNeighbor(const std::shared_ptr& neighbor); +private: + std::string id_; + std::vector> neighbors_; +}; diff --git a/src/Graph.cpp b/src/Graph.cpp new file mode 100644 index 0000000..4f1fa95 --- /dev/null +++ b/src/Graph.cpp @@ -0,0 +1,46 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2024 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 . + +#include + +#include + +const std::map>& Graph::getVertices() const +{ + return vertices_; +} + +void Graph::addEdge(const std::string& vertexId1, const std::string& vertexId2) +{ + auto v1 = findOrAddVertex(vertexId1); + auto v2 = findOrAddVertex(vertexId2); + v1->addNeighbor(v2); + v2->addNeighbor(v1); +} + +std::shared_ptr Graph::findOrAddVertex(const std::string& vertexId) +{ + auto iter = vertices_.find(vertexId); + if (iter != vertices_.end()) + { + return (*iter).second; + } + else + { + auto v = std::make_shared(vertexId); + vertices_.insert({ vertexId, v }); + return v; + } +} diff --git a/src/LanParty.cpp b/src/LanParty.cpp new file mode 100644 index 0000000..0246a0e --- /dev/null +++ b/src/LanParty.cpp @@ -0,0 +1,85 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2024 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 . + +#include + +std::string LanParty::getPuzzleName() const +{ + return "Day 23: LAN Party"; +} + +std::string LanParty::getInputFileName() const +{ + return "lan_party.txt"; +} + +void LanParty::processDataLine(const std::string& line) +{ + lan_.addEdge(line.substr(0, 2), line.substr(3, 2)); +} + +void LanParty::finish() +{ + auto vertices = lan_.getVertices(); + // This works as long as "ta" is present as a computername, otherwise we would have to use + // vertices.find_if(). + auto iterTx = vertices.find(getFirstTxComputerName()); + while (iterTx != vertices.end() && iterTx->second->getId() <= getLastTxComputerName()) + { + countInterconnectedThreeSets(*iterTx->second); + iterTx++; + } +} + +void LanParty::countInterconnectedThreeSets(const Vertex& vertexTx) +{ + auto neighborsOfTx = vertexTx.getNeighbors(); + for (size_t i = 0; i < neighborsOfTx.size(); i++) + { + auto vertexA = neighborsOfTx[i].lock(); + if (shallProcessVertex(*vertexA, vertexTx)) + { + for (size_t j{ i + 1 }; j < neighborsOfTx.size(); j++) + { + auto vertexB = neighborsOfTx[j].lock(); + if (shallProcessVertex(*vertexB, vertexTx)) + { + for (auto& neighborOfA : vertexA->getNeighbors()) + { + if (vertexB == neighborOfA.lock()) + { + part1++; + } + } + } + } + } + } +} + +bool LanParty::shallProcessVertex(const Vertex& vertexToCheck, const Vertex& vertexTx) const +{ + return (vertexToCheck.getId()[0] != 't' || vertexToCheck.getId() > vertexTx.getId()); +} + +const std::string LanParty::getFirstTxComputerName() const +{ + return "ta"; +} + +const std::string LanParty::getLastTxComputerName() const +{ + return "tz"; +} diff --git a/src/Program.cpp b/src/Program.cpp index 6e3a9e1..12301be 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -28,6 +28,7 @@ #include #include #include +#include void Program::run() { @@ -52,6 +53,7 @@ void Program::runSolvers() runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); + runSolver(solverEngine); } std::vector Program::getInputPaths() const diff --git a/src/Vertex.cpp b/src/Vertex.cpp new file mode 100644 index 0000000..c6f31b7 --- /dev/null +++ b/src/Vertex.cpp @@ -0,0 +1,38 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2024 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 . + +#include + +#include + +Vertex::Vertex(const std::string id) + : id_{ id }, neighbors_{} +{ +} + +std::string Vertex::getId() const +{ + return id_; +} + +const std::vector>& Vertex::getNeighbors() const +{ + return neighbors_; +} + +void Vertex::addNeighbor(const std::shared_ptr& neighbor) +{ + neighbors_.push_back(neighbor); +} diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index e9990a1..85e70a2 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #define REQUIRE_MESSAGE(cond, msg) if (!(cond)) { INFO(msg); REQUIRE(cond); } @@ -116,3 +117,16 @@ TEST_CASE("[HoofItTests]") test.run(std::make_unique(), 36, 81, test.getExampleInputPaths()); } } + +TEST_CASE("[LanPartyTests]") +{ + TestContext test; + SECTION("FullData") + { + test.run(std::make_unique(), 1230, 0, test.getInputPaths()); + } + SECTION("ExampleData") + { + test.run(std::make_unique(), 7, 0, test.getExampleInputPaths()); + } +}