Add solutions for "Day 4: Ceres Search"

This commit is contained in:
Stefan Müller 2024-12-04 18:45:02 +01:00
parent 08ddddacff
commit 4f049c06d8
11 changed files with 328 additions and 2 deletions

View File

@ -129,7 +129,9 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AdventOfCode2024.cpp" />
<ClCompile Include="CeresSearch.cpp" />
<ClCompile Include="HistorianHysteria.cpp" />
<ClCompile Include="LinesSolver.cpp" />
<ClCompile Include="MullDataState.cpp" />
<ClCompile Include="MullToggleCloseState.cpp" />
<ClCompile Include="MullDoOpenState.cpp" />
@ -139,6 +141,7 @@
<ClCompile Include="MullItOver.cpp" />
<ClCompile Include="MullStates.cpp" />
<ClCompile Include="MullCharState.cpp" />
<ClCompile Include="Point2.cpp" />
<ClCompile Include="Program.cpp" />
<ClCompile Include="RedNosedReports.cpp" />
<ClCompile Include="Solver.cpp" />
@ -147,7 +150,9 @@
<ClCompile Include="StringStateMachine.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CeresSearch.h" />
<ClInclude Include="HistorianHysteria.h" />
<ClInclude Include="LinesSolver.h" />
<ClInclude Include="MullDataState.h" />
<ClInclude Include="MullToggleCloseState.h" />
<ClInclude Include="MullDoOpenState.h" />
@ -157,6 +162,7 @@
<ClInclude Include="MullItOver.h" />
<ClInclude Include="MullStates.h" />
<ClInclude Include="MullCharState.h" />
<ClInclude Include="Point2.h" />
<ClInclude Include="Program.h" />
<ClInclude Include="RedNosedReportData.h" />
<ClInclude Include="RedNosedReports.h" />

View File

@ -66,6 +66,15 @@
<ClCompile Include="MullStates.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Point2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CeresSearch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LinesSolver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SolverEngine.h">
@ -122,5 +131,14 @@
<ClInclude Include="MullDataState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Point2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CeresSearch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LinesSolver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,80 @@
// 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 <http://www.gnu.org/licenses/>.
#include "CeresSearch.h"
std::string CeresSearch::getPuzzleName() const
{
return "Day 4: Ceres Search";
}
std::string CeresSearch::getInputFileName() const
{
return "ceres_search.txt";
}
void CeresSearch::finish()
{
for (int j = 0; j < lines.size(); j++)
{
for (int i = 0; i < lines[j].size(); i++)
{
if (lines[j][i] == xmas[0])
{
Point2 start{ i, j };
computeXmasCount(start);
}
else if (lines[j][i] == xmas[2])
{
Point2 start{ i, j };
computeX_MasCount(start);
}
}
}
}
void CeresSearch::computeXmasCount(const Point2& start)
{
for (auto d : Point2::directions)
{
auto p{ start + d };
auto i{ 1 };
while (i < 4 && isInBounds(p) && xmas[i] == getPosition(p))
{
p += d;
i++;
}
if (i == 4)
{
part1++;
}
}
}
void CeresSearch::computeX_MasCount(const Point2& start)
{
auto pUL{ start + Point2::upLeft };
auto pDR{ start + Point2::downRight };
auto pUR{ start + Point2::upRight };
auto pDL{ start + Point2::downLeft };
if (isInBounds(pUL) && isInBounds(pDR)
&& ((getPosition(pUL) == xmas[1] && getPosition(pDR) == xmas[3])
|| (getPosition(pUL) == xmas[3] && getPosition(pDR) == xmas[1]))
&& ((getPosition(pUR) == xmas[1] && getPosition(pDL) == xmas[3])
|| (getPosition(pUR) == xmas[3] && getPosition(pDL) == xmas[1])))
{
part2++;
}
}

View File

@ -0,0 +1,33 @@
// 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 <http://www.gnu.org/licenses/>.
#pragma once
#include <vector>
#include "LinesSolver.h"
class CeresSearch :
public LinesSolver
{
public:
std::string getPuzzleName() const override;
std::string getInputFileName() const override;
void finish() override;
private:
char xmas[4] = { 'X', 'M', 'A', 'S' };
void computeXmasCount(const Point2& start);
void computeX_MasCount(const Point2& start);
};

View File

@ -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 <http://www.gnu.org/licenses/>.
#include "LinesSolver.h"
void LinesSolver::processDataLine(const std::string& line)
{
lines.push_back(line);
}
bool LinesSolver::isInBounds(const Point2& point)
{
return 0 <= point.y && point.y < lines.size()
&& 0 <= point.x && point.x < lines[point.y].size();
}
char LinesSolver::getPosition(const Point2& point)
{
return lines[point.y][point.x];
}

View File

@ -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 <http://www.gnu.org/licenses/>.
#pragma once
#include <vector>
#include "Solver.h"
#include "Point2.h"
class LinesSolver :
public Solver
{
public:
void processDataLine(const std::string& line) override;
protected:
std::vector<std::string> lines{};
bool isInBounds(const Point2& point);
char getPosition(const Point2& point);
};

View File

@ -0,0 +1,81 @@
// 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 <http://www.gnu.org/licenses/>.
#include "Point2.h"
Point2::Point2()
: Point2{ 0, 0 } {}
Point2::Point2(const int x, const int y)
: x{ x }, y{ y } {}
bool Point2::operator==(const Point2& rhs) const
{
return x == rhs.x && y == rhs.y;
}
bool Point2::operator!=(const Point2& rhs) const
{
return !(x == y);
}
Point2 Point2::operator+(const Point2& rhs) const
{
return Point2(x + rhs.x, y + rhs.y);
}
Point2 Point2::operator-(const Point2& rhs) const
{
return Point2(x - rhs.x, y - rhs.y);
}
Point2 Point2::operator*(const int rhs) const
{
return Point2(x * rhs, y * rhs);
}
Point2 Point2::operator-() const
{
return Point2(-x, -y);
}
Point2& Point2::operator+=(const Point2& rhs)
{
*this = *this + rhs;
return *this;
}
Point2& Point2::operator-=(const Point2& rhs)
{
*this = *this - rhs;
return *this;
}
Point2& Point2::operator*=(const int rhs)
{
*this = *this * rhs;
return *this;
}
const Point2 Point2::left{ -1, 0 };
const Point2 Point2::right{ 1, 0 };
const Point2 Point2::up{ 0, -1 };
const Point2 Point2::down{ 0, 1 };
const Point2 Point2::upLeft{ -1, -1 };
const Point2 Point2::upRight{ 1, -1 };
const Point2 Point2::downLeft{ -1, 1 };
const Point2 Point2::downRight{ 1, 1 };
const Point2 Point2::directions[] = { Point2::left, Point2::right, Point2::up, Point2::down,
Point2::upLeft, Point2::upRight, Point2::downLeft, Point2::downRight };

36
AdventOfCode2024/Point2.h Normal file
View File

@ -0,0 +1,36 @@
// 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 <http://www.gnu.org/licenses/>.
#pragma once
class Point2
{
public:
int x, y;
Point2();
Point2(const int x, const int y);
bool operator==(const Point2& rhs) const;
bool operator!=(const Point2& rhs) const;
Point2 operator+(const Point2& rhs) const;
Point2 operator-(const Point2& rhs) const;
Point2 operator*(const int rhs) const;
Point2 operator-() const;
Point2& operator+=(const Point2& rhs);
Point2& operator-=(const Point2& rhs);
Point2& operator*=(const int rhs);
static const Point2 left, right, up, down;
static const Point2 upLeft, upRight, downLeft, downRight;
static const Point2 directions[8];
};

View File

@ -23,6 +23,7 @@
#include "HistorianHysteria.h"
#include "RedNosedReports.h"
#include "MullItOver.h"
#include "CeresSearch.h"
void Program::run()
{
@ -36,6 +37,7 @@ void Program::runSolvers()
solverEngine.run(*std::make_unique<HistorianHysteria>());
solverEngine.run(*std::make_unique<RedNosedReports>());
solverEngine.run(*std::make_unique<MullItOver>());
solverEngine.run(*std::make_unique<CeresSearch>());
}
std::vector<std::string> Program::getInputPaths() const

View File

@ -101,8 +101,8 @@
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;..\$(Platform)\$(Configuration);D:\Projects\VS\AdventOfCode2024Full\code\AdventOfCode2024\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Solver.obj;SolverEngine.obj;HistorianHysteria.obj;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Solver.obj;SolverEngine.obj;HistorianHysteria.obj;RedNosedReports.obj;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

View File

@ -32,6 +32,12 @@ Here, we have a few conditionals to determine on the fly which of the numbers wo
A simple [finite state machine](AdventOfCode2024/StringStateMachine.h) crawling along the input character by character solves both parts nicely. The algorithm tracks whether `mul` instructions are enabled or not, but ignores this setting for part 1.
### Day 4: Ceres Search
:mag_right: Puzzle: <https://adventofcode.com/2024/day/4>, :white_check_mark: Solver: [`CeresSearch.cpp`](AdventOfCode2024/CeresSearch.cpp)
For this puzzle I added a class for [points in two-dimensional space](AdventOfCode2024/Point2.h), so I can use these for simplifying directional computations. With that, the algorithm looks for all `X` and `A` for part 1 and 2, respectively, and tries to find the remaining characters, starting from that `X` or `A`.
## License
Copyright (C) 2024 Stefan Müller