From e1cd0867cb988ccf632614439d292fa25dd80917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Tue, 4 Feb 2025 17:43:20 +0100 Subject: [PATCH] Add solution for "Day 8: Resonant Collinearity", part 2 The Point2::operator<() was introduced for set, which is not actually required. --- README.md | 6 ++++ include/aoc/Point2.hpp | 1 - include/aoc/ResonantCollinearity.hpp | 9 ++--- src/Point2.cpp | 5 --- src/ResonantCollinearity.cpp | 51 ++++++++++++++++++++++------ tests/src/TestCases.cpp | 5 +-- 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index b3c15db..273800f 100644 --- a/README.md +++ b/README.md @@ -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. +### Day 8: Resonant Collinearity + +:mag_right: Puzzle: , :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 :mag_right: Puzzle: , :white_check_mark: Solver: [`HoofIt.cpp`](src/HoofIt.cpp) diff --git a/include/aoc/Point2.hpp b/include/aoc/Point2.hpp index 538c801..8e3caf3 100644 --- a/include/aoc/Point2.hpp +++ b/include/aoc/Point2.hpp @@ -34,7 +34,6 @@ class Point2 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; Point2 operator+(const Point2& rhs) const; Point2 operator-(const Point2& rhs) const; Point2 operator*(const int rhs) const; diff --git a/include/aoc/ResonantCollinearity.hpp b/include/aoc/ResonantCollinearity.hpp index 64270a1..925c388 100644 --- a/include/aoc/ResonantCollinearity.hpp +++ b/include/aoc/ResonantCollinearity.hpp @@ -16,9 +16,9 @@ #pragma once #include -#include #include +#include #include #include @@ -32,7 +32,8 @@ class ResonantCollinearity private: static constexpr char getEmptyChar(); std::map> antennas_{}; - std::set antinodes_{}; - void addNewAntenna(Point2&& newPosition); - void addNewAntinode(Point2&& newPosition); + void addNewAntenna(Grid& antinodeGrid1, Grid& antinodeGrid2, Point2&& newPosition); + void findNewAntinodes(Grid& antinodeGrid1, Grid& antinodeGrid2, Point2&& start, + const Point2& increment); + void addNewAntinode(Grid& antinodeGrid, Point2& newPosition, long long int& part); }; diff --git a/src/Point2.cpp b/src/Point2.cpp index f3a6de3..1103915 100644 --- a/src/Point2.cpp +++ b/src/Point2.cpp @@ -47,11 +47,6 @@ bool Point2::operator!=(const Point2& rhs) const 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 { return Point2(x + rhs.x, y + rhs.y); diff --git a/src/ResonantCollinearity.cpp b/src/ResonantCollinearity.cpp index 9dea232..242d0c5 100644 --- a/src/ResonantCollinearity.cpp +++ b/src/ResonantCollinearity.cpp @@ -29,18 +29,21 @@ const std::string ResonantCollinearity::getInputFileName() const void ResonantCollinearity::finish() { + Grid antinodeGrid1{ lines.size(), lines[0].size() }; + antinodeGrid1.fill(false); + Grid antinodeGrid2{ lines.size(), lines[0].size() }; + antinodeGrid2.fill(false); + for (int j = 0; j < lines.size(); j++) { for (int i = 0; i < lines[j].size(); i++) { if (lines[j][i] != getEmptyChar()) { - addNewAntenna({ i, j }); + addNewAntenna(antinodeGrid1, antinodeGrid2, { i, j }); } } } - - part1 = antinodes_.size(); } constexpr char ResonantCollinearity::getEmptyChar() @@ -48,25 +51,53 @@ constexpr char ResonantCollinearity::getEmptyChar() return '.'; } -void ResonantCollinearity::addNewAntenna(Point2&& newPosition) +void ResonantCollinearity::addNewAntenna(Grid& antinodeGrid1, Grid& antinodeGrid2, Point2&& newPosition) { const auto [it, success] = antennas_.insert({ getPosition(newPosition), { newPosition } }); 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(oldPosition * 2 - newPosition); + addNewAntinode(antinodeGrid2, it->second.front(), part2); + } + 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); } } -void ResonantCollinearity::addNewAntinode(Point2&& newPosition) +void ResonantCollinearity::findNewAntinodes(Grid& antinodeGrid1, Grid& 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& antinodeGrid, Point2& newPosition, long long int& count) +{ + if (!antinodeGrid[newPosition.y][newPosition.x]) + { + antinodeGrid[newPosition.y][newPosition.x] = true; + count++; } } diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index 00174c0..cb592a4 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -126,11 +127,11 @@ TEST_CASE("[ResonantCollinearityTests]") TestContext test; SECTION("FullData") { - test.run(std::make_unique(), 426, 0, test.getInputPaths()); + test.run(std::make_unique(), 426, 1359, test.getInputPaths()); } SECTION("ExampleData") { - test.run(std::make_unique(), 14, 0, test.getExampleInputPaths()); + test.run(std::make_unique(), 14, 34, test.getExampleInputPaths()); } }