diff --git a/include/aoc/GardenGroups.hpp b/include/aoc/GardenGroups.hpp new file mode 100644 index 0000000..b4ad1f1 --- /dev/null +++ b/include/aoc/GardenGroups.hpp @@ -0,0 +1,33 @@ +// 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 . + +#pragma once + +#include + +#include +#include +#include + +class GardenGroups + : public LinesSolver +{ +public: + virtual const std::string getPuzzleName() const override; + virtual const std::string getInputFileName() const override; + virtual void finish() override; +private: + void traverseRegion(Grid& isVisited, std::stack& otherRegionsStack, const Point2& start); +}; diff --git a/src/GardenGroups.cpp b/src/GardenGroups.cpp new file mode 100644 index 0000000..44dc3aa --- /dev/null +++ b/src/GardenGroups.cpp @@ -0,0 +1,93 @@ +// 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 . + +#include + +const std::string GardenGroups::getPuzzleName() const +{ + return "Day 12: Garden Groups"; +} + +const std::string GardenGroups::getInputFileName() const +{ + return "garden_groups.txt"; +} + +void GardenGroups::finish() +{ + Grid isVisited{ lines.size(), lines[0].size() }; + isVisited.fill(false); + + std::stack otherRegionsStack{}; + otherRegionsStack.emplace(0, 0); + while (!otherRegionsStack.empty()) + { + const Point2 position{ otherRegionsStack.top() }; + otherRegionsStack.pop(); + if (!isVisited.cell(position)) + { + traverseRegion(isVisited, otherRegionsStack, position); + } + } +} + +void GardenGroups::traverseRegion(Grid& isVisited, std::stack& otherRegionsStack, const Point2& start) +{ + const char plantType{ getCharAt(start) }; + long long int area{ 0 }; + long long int perimeter{ 0 }; + std::stack regionStack{}; + regionStack.push(start); + + while (!regionStack.empty()) + { + const Point2 position{ regionStack.top() }; + regionStack.pop(); + if (!isVisited.cell(position)) + { + isVisited.cell(position) = true; + area++; + + for (const Point2& direction : Point2::cardinalDirections) + { + const Point2 next{ position + direction }; + if (isInBounds(next)) + { + if (getCharAt(next) == plantType) + { + if (!isVisited.cell(next)) + { + regionStack.push(next); + } + } + else + { + perimeter++; + if (!isVisited.cell(next)) + { + otherRegionsStack.push(next); + } + } + } + else + { + perimeter++; + } + } + } + } + + part1 += area * perimeter; +} diff --git a/src/Program.cpp b/src/Program.cpp index 8d3f1f1..9e20db1 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include void Program::run() @@ -61,6 +62,7 @@ void Program::runSolvers() runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); + runSolver(solverEngine); runSolver(solverEngine); } diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index 2248abc..b63e40a 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -15,6 +15,9 @@ #include +#include + +// Solver implementations in day order. #include #include #include @@ -26,8 +29,8 @@ #include #include #include +#include #include -#include #define REQUIRE_MESSAGE(cond, msg) if (!(cond)) { INFO(msg); REQUIRE(cond); } @@ -174,6 +177,19 @@ TEST_CASE("[PlutonianPebblesTests]") } } +TEST_CASE("[GardenGroupsTests]") +{ + TestContext test; + SECTION("FullData") + { + test.run(std::make_unique(), 1477762, 0, test.getInputPaths()); + } + SECTION("ExampleData") + { + test.run(std::make_unique(), 1930, 0, test.getExampleInputPaths()); + } +} + TEST_CASE("[LanPartyTests]") { TestContext test;