diff --git a/AdventOfCode2024/AdventOfCode2024.vcxproj b/AdventOfCode2024/AdventOfCode2024.vcxproj
index 090671f..46d2eb9 100644
--- a/AdventOfCode2024/AdventOfCode2024.vcxproj
+++ b/AdventOfCode2024/AdventOfCode2024.vcxproj
@@ -129,7 +129,9 @@
+
+
@@ -139,6 +141,7 @@
+
@@ -147,7 +150,9 @@
+
+
@@ -157,6 +162,7 @@
+
diff --git a/AdventOfCode2024/AdventOfCode2024.vcxproj.filters b/AdventOfCode2024/AdventOfCode2024.vcxproj.filters
index 1d87b0d..12b5bc2 100644
--- a/AdventOfCode2024/AdventOfCode2024.vcxproj.filters
+++ b/AdventOfCode2024/AdventOfCode2024.vcxproj.filters
@@ -66,6 +66,15 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -122,5 +131,14 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/AdventOfCode2024/CeresSearch.cpp b/AdventOfCode2024/CeresSearch.cpp
new file mode 100644
index 0000000..538dc12
--- /dev/null
+++ b/AdventOfCode2024/CeresSearch.cpp
@@ -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 .
+
+#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++;
+ }
+}
diff --git a/AdventOfCode2024/CeresSearch.h b/AdventOfCode2024/CeresSearch.h
new file mode 100644
index 0000000..568df15
--- /dev/null
+++ b/AdventOfCode2024/CeresSearch.h
@@ -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 .
+
+#pragma once
+
+#include
+
+#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);
+};
diff --git a/AdventOfCode2024/LinesSolver.cpp b/AdventOfCode2024/LinesSolver.cpp
new file mode 100644
index 0000000..f6b68ee
--- /dev/null
+++ b/AdventOfCode2024/LinesSolver.cpp
@@ -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 .
+
+#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];
+}
diff --git a/AdventOfCode2024/LinesSolver.h b/AdventOfCode2024/LinesSolver.h
new file mode 100644
index 0000000..9a2d8bb
--- /dev/null
+++ b/AdventOfCode2024/LinesSolver.h
@@ -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 "Solver.h"
+#include "Point2.h"
+
+class LinesSolver :
+ public Solver
+{
+public:
+ void processDataLine(const std::string& line) override;
+protected:
+ std::vector lines{};
+ bool isInBounds(const Point2& point);
+ char getPosition(const Point2& point);
+};
diff --git a/AdventOfCode2024/Point2.cpp b/AdventOfCode2024/Point2.cpp
new file mode 100644
index 0000000..c8843ed
--- /dev/null
+++ b/AdventOfCode2024/Point2.cpp
@@ -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 .
+
+#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 };
diff --git a/AdventOfCode2024/Point2.h b/AdventOfCode2024/Point2.h
new file mode 100644
index 0000000..ef32241
--- /dev/null
+++ b/AdventOfCode2024/Point2.h
@@ -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 .
+
+#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];
+};
diff --git a/AdventOfCode2024/Program.cpp b/AdventOfCode2024/Program.cpp
index d5364de..a36ee63 100644
--- a/AdventOfCode2024/Program.cpp
+++ b/AdventOfCode2024/Program.cpp
@@ -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());
solverEngine.run(*std::make_unique());
solverEngine.run(*std::make_unique());
+ solverEngine.run(*std::make_unique());
}
std::vector Program::getInputPaths() const
diff --git a/AdventOfCode2024/UnitTests/UnitTests.vcxproj b/AdventOfCode2024/UnitTests/UnitTests.vcxproj
index f4b1153..c5dd3f5 100644
--- a/AdventOfCode2024/UnitTests/UnitTests.vcxproj
+++ b/AdventOfCode2024/UnitTests/UnitTests.vcxproj
@@ -101,8 +101,8 @@
Windows
- $(VCInstallDir)UnitTest\lib;..\$(Platform)\$(Configuration);D:\Projects\VS\AdventOfCode2024Full\code\AdventOfCode2024\x64\Debug;%(AdditionalLibraryDirectories)
- Solver.obj;SolverEngine.obj;HistorianHysteria.obj;%(AdditionalDependencies)
+ $(VCInstallDir)UnitTest\lib;$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
+ Solver.obj;SolverEngine.obj;HistorianHysteria.obj;RedNosedReports.obj;%(AdditionalDependencies)
diff --git a/README.md b/README.md
index 3ae75e5..c6fe225 100644
--- a/README.md
+++ b/README.md
@@ -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: , :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