Add solution for "Day 8: Resonant Collinearity", part 2

The Point2::operator<() was introduced for set<Point2>, which is not actually required.
This commit is contained in:
Stefan Müller 2025-02-04 17:43:20 +01:00
parent 44f2a0e0ec
commit e1cd0867cb
6 changed files with 55 additions and 22 deletions

View File

@ -50,6 +50,12 @@ My implementation uses an ordering matrix (a two-dimensional boolean array) to t
The algorithm recursively tries the different operators from left to right until all the calibration numbers have been used. Since the result from any of the operator cannot be less than its operands, any branch of the recursion that surpasses the test value can be aborted. The algorithm recursively tries the different operators from left to right until all the calibration numbers have been used. Since the result from any of the operator cannot be less than its operands, any branch of the recursion that surpasses the test value can be aborted.
### Day 8: Resonant Collinearity
:mag_right: Puzzle: <https://adventofcode.com/2024/day/8>, :white_check_mark: Solver: [`ResonantCollinearity.cpp`](src/ResonantCollinearity.cpp)
For any pair of antennas of the same frequency, the algorithm adds the difference of their positions to one of these positions and subtracts it from the other to find the antinodes. For part 2, this process is repeated for each of the two directions until the found antinodes leave the defined area. Counting duplicate antinodes is prevented by keeping track of their locations in a two-dimensional array covering the area.
### Day 10: Hoof It ### Day 10: Hoof It
:mag_right: Puzzle: <https://adventofcode.com/2024/day/10>, :white_check_mark: Solver: [`HoofIt.cpp`](src/HoofIt.cpp) :mag_right: Puzzle: <https://adventofcode.com/2024/day/10>, :white_check_mark: Solver: [`HoofIt.cpp`](src/HoofIt.cpp)

View File

@ -34,7 +34,6 @@ class Point2
Point2(const int x, const int y); Point2(const int x, const int y);
bool operator==(const Point2& rhs) const; bool operator==(const Point2& rhs) const;
bool operator!=(const Point2& rhs) const; 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 Point2& rhs) const; Point2 operator-(const Point2& rhs) const;
Point2 operator*(const int rhs) const; Point2 operator*(const int rhs) const;

View File

@ -16,9 +16,9 @@
#pragma once #pragma once
#include <map> #include <map>
#include <set>
#include <vector> #include <vector>
#include <aoc/Grid.hpp>
#include <aoc/LinesSolver.hpp> #include <aoc/LinesSolver.hpp>
#include <aoc/Point2.hpp> #include <aoc/Point2.hpp>
@ -32,7 +32,8 @@ class ResonantCollinearity
private: private:
static constexpr char getEmptyChar(); static constexpr char getEmptyChar();
std::map<char, std::vector<Point2>> antennas_{}; std::map<char, std::vector<Point2>> antennas_{};
std::set<Point2> antinodes_{}; void addNewAntenna(Grid<bool>& antinodeGrid1, Grid<bool>& antinodeGrid2, Point2&& newPosition);
void addNewAntenna(Point2&& newPosition); void findNewAntinodes(Grid<bool>& antinodeGrid1, Grid<bool>& antinodeGrid2, Point2&& start,
void addNewAntinode(Point2&& newPosition); const Point2& increment);
void addNewAntinode(Grid<bool>& antinodeGrid, Point2& newPosition, long long int& part);
}; };

View File

@ -47,11 +47,6 @@ bool Point2::operator!=(const Point2& rhs) const
return !(*this == rhs); return !(*this == rhs);
} }
bool Point2::operator<(const Point2& rhs) const
{
return x < rhs.x || (x == rhs.x && y < rhs.y);
}
Point2 Point2::operator+(const Point2& rhs) const Point2 Point2::operator+(const Point2& rhs) const
{ {
return Point2(x + rhs.x, y + rhs.y); return Point2(x + rhs.x, y + rhs.y);

View File

@ -29,18 +29,21 @@ const std::string ResonantCollinearity::getInputFileName() const
void ResonantCollinearity::finish() void ResonantCollinearity::finish()
{ {
Grid<bool> antinodeGrid1{ lines.size(), lines[0].size() };
antinodeGrid1.fill(false);
Grid<bool> antinodeGrid2{ lines.size(), lines[0].size() };
antinodeGrid2.fill(false);
for (int j = 0; j < lines.size(); j++) for (int j = 0; j < lines.size(); j++)
{ {
for (int i = 0; i < lines[j].size(); i++) for (int i = 0; i < lines[j].size(); i++)
{ {
if (lines[j][i] != getEmptyChar()) if (lines[j][i] != getEmptyChar())
{ {
addNewAntenna({ i, j }); addNewAntenna(antinodeGrid1, antinodeGrid2, { i, j });
} }
} }
} }
part1 = antinodes_.size();
} }
constexpr char ResonantCollinearity::getEmptyChar() constexpr char ResonantCollinearity::getEmptyChar()
@ -48,25 +51,53 @@ constexpr char ResonantCollinearity::getEmptyChar()
return '.'; return '.';
} }
void ResonantCollinearity::addNewAntenna(Point2&& newPosition) void ResonantCollinearity::addNewAntenna(Grid<bool>& antinodeGrid1, Grid<bool>& antinodeGrid2, Point2&& newPosition)
{ {
const auto [it, success] = antennas_.insert({ getPosition(newPosition), { newPosition } }); const auto [it, success] = antennas_.insert({ getPosition(newPosition), { newPosition } });
if (!success) if (!success)
{ {
for (const auto& oldPosition : it->second) // Adds the new antenna position itself as an antinode for part 2.
if (it->second.size() == 1)
{ {
addNewAntinode(newPosition * 2 - oldPosition); addNewAntinode(antinodeGrid2, it->second.front(), part2);
addNewAntinode(oldPosition * 2 - newPosition); }
addNewAntinode(antinodeGrid2, newPosition, part2);
// Adds antinodes for all pairs of the new antenna position and each of the already processed other antenna
// positions with the same frequency.
for (const auto& other : it->second)
{
Point2 diff = newPosition - other;
findNewAntinodes(antinodeGrid1, antinodeGrid2, newPosition + diff, diff);
diff = -diff;
findNewAntinodes(antinodeGrid1, antinodeGrid2, other + diff, diff);
} }
it->second.push_back(newPosition); it->second.push_back(newPosition);
} }
} }
void ResonantCollinearity::addNewAntinode(Point2&& newPosition) void ResonantCollinearity::findNewAntinodes(Grid<bool>& antinodeGrid1, Grid<bool>& antinodeGrid2, Point2&& start,
const Point2& increment)
{ {
if (isInBounds(newPosition)) if (isInBounds(start))
{ {
antinodes_.insert(newPosition); addNewAntinode(antinodeGrid1, start, part1);
addNewAntinode(antinodeGrid2, start, part2);
start += increment;
while (isInBounds(start))
{
addNewAntinode(antinodeGrid2, start, part2);
start += increment;
}
}
}
void ResonantCollinearity::addNewAntinode(Grid<bool>& antinodeGrid, Point2& newPosition, long long int& count)
{
if (!antinodeGrid[newPosition.y][newPosition.x])
{
antinodeGrid[newPosition.y][newPosition.x] = true;
count++;
} }
} }

View File

@ -23,6 +23,7 @@
#include <aoc/GuardGallivant.hpp> #include <aoc/GuardGallivant.hpp>
#include <aoc/BridgeRepair.hpp> #include <aoc/BridgeRepair.hpp>
#include <aoc/ResonantCollinearity.hpp> #include <aoc/ResonantCollinearity.hpp>
#include <aoc/DiskFragmenter.hpp>
#include <aoc/HoofIt.hpp> #include <aoc/HoofIt.hpp>
#include <aoc/PlutonianPebbles.hpp> #include <aoc/PlutonianPebbles.hpp>
#include <aoc/LanParty.hpp> #include <aoc/LanParty.hpp>
@ -126,11 +127,11 @@ TEST_CASE("[ResonantCollinearityTests]")
TestContext test; TestContext test;
SECTION("FullData") SECTION("FullData")
{ {
test.run(std::make_unique<ResonantCollinearity>(), 426, 0, test.getInputPaths()); test.run(std::make_unique<ResonantCollinearity>(), 426, 1359, test.getInputPaths());
} }
SECTION("ExampleData") SECTION("ExampleData")
{ {
test.run(std::make_unique<ResonantCollinearity>(), 14, 0, test.getExampleInputPaths()); test.run(std::make_unique<ResonantCollinearity>(), 14, 34, test.getExampleInputPaths());
} }
} }