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