Add solution for "Day 12: Garden Groups", part 1
This commit is contained in:
parent
8bea3c2c48
commit
28baf4db3e
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
#include <aoc/Grid.hpp>
|
||||||
|
#include <aoc/LinesSolver.hpp>
|
||||||
|
#include <aoc/Point2.hpp>
|
||||||
|
|
||||||
|
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<bool>& isVisited, std::stack<Point2>& otherRegionsStack, const Point2& start);
|
||||||
|
};
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <aoc/GardenGroups.hpp>
|
||||||
|
|
||||||
|
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<bool> isVisited{ lines.size(), lines[0].size() };
|
||||||
|
isVisited.fill(false);
|
||||||
|
|
||||||
|
std::stack<Point2> 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<bool>& isVisited, std::stack<Point2>& otherRegionsStack, const Point2& start)
|
||||||
|
{
|
||||||
|
const char plantType{ getCharAt(start) };
|
||||||
|
long long int area{ 0 };
|
||||||
|
long long int perimeter{ 0 };
|
||||||
|
std::stack<Point2> 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;
|
||||||
|
}
|
|
@ -32,6 +32,7 @@
|
||||||
#include <aoc/DiskFragmenter.hpp>
|
#include <aoc/DiskFragmenter.hpp>
|
||||||
#include <aoc/HoofIt.hpp>
|
#include <aoc/HoofIt.hpp>
|
||||||
#include <aoc/PlutonianPebbles.hpp>
|
#include <aoc/PlutonianPebbles.hpp>
|
||||||
|
#include <aoc/GardenGroups.hpp>
|
||||||
#include <aoc/LanParty.hpp>
|
#include <aoc/LanParty.hpp>
|
||||||
|
|
||||||
void Program::run()
|
void Program::run()
|
||||||
|
@ -61,6 +62,7 @@ void Program::runSolvers()
|
||||||
runSolver<DiskFragmenter>(solverEngine);
|
runSolver<DiskFragmenter>(solverEngine);
|
||||||
runSolver<HoofIt>(solverEngine);
|
runSolver<HoofIt>(solverEngine);
|
||||||
runSolver<PlutonianPebbles>(solverEngine);
|
runSolver<PlutonianPebbles>(solverEngine);
|
||||||
|
runSolver<GardenGroups>(solverEngine);
|
||||||
runSolver<LanParty>(solverEngine);
|
runSolver<LanParty>(solverEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include <aocTests/TestContext.hpp>
|
||||||
|
|
||||||
|
// Solver implementations in day order.
|
||||||
#include <aoc/HistorianHysteria.hpp>
|
#include <aoc/HistorianHysteria.hpp>
|
||||||
#include <aoc/RedNosedReports.hpp>
|
#include <aoc/RedNosedReports.hpp>
|
||||||
#include <aoc/MullItOver.hpp>
|
#include <aoc/MullItOver.hpp>
|
||||||
|
@ -26,8 +29,8 @@
|
||||||
#include <aoc/DiskFragmenter.hpp>
|
#include <aoc/DiskFragmenter.hpp>
|
||||||
#include <aoc/HoofIt.hpp>
|
#include <aoc/HoofIt.hpp>
|
||||||
#include <aoc/PlutonianPebbles.hpp>
|
#include <aoc/PlutonianPebbles.hpp>
|
||||||
|
#include <aoc/GardenGroups.hpp>
|
||||||
#include <aoc/LanParty.hpp>
|
#include <aoc/LanParty.hpp>
|
||||||
#include <aocTests/TestContext.hpp>
|
|
||||||
|
|
||||||
#define REQUIRE_MESSAGE(cond, msg) if (!(cond)) { INFO(msg); REQUIRE(cond); }
|
#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<GardenGroups>(), 1477762, 0, test.getInputPaths());
|
||||||
|
}
|
||||||
|
SECTION("ExampleData")
|
||||||
|
{
|
||||||
|
test.run(std::make_unique<GardenGroups>(), 1930, 0, test.getExampleInputPaths());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("[LanPartyTests]")
|
TEST_CASE("[LanPartyTests]")
|
||||||
{
|
{
|
||||||
TestContext test;
|
TestContext test;
|
||||||
|
|
Loading…
Reference in New Issue