From 45bfdf7b66ce752f08003e78cae426cc9d2f915b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sat, 21 Feb 2026 09:40:43 +0100 Subject: [PATCH 01/14] Start Aoc 2021 Day 19 generating rotations symbolically ("S4") --- adventofcode/2021/day/19/beacon_scanner.cpp | 123 ++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 adventofcode/2021/day/19/beacon_scanner.cpp diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp new file mode 100644 index 0000000..01e466d --- /dev/null +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +struct symbol { + std::bitset<2> id; + bool negative; + symbol& operator-() { + negative = !negative; + return *this; + } + bool operator==(symbol const& that) const { + return id == that.id && negative == that.negative; + } +}; + +std::size_t hash_value(symbol const& s) { + return s.id.to_ullong() ^ s.negative; +} + +void print(symbol const& s) { + std::cout << (s.negative ? '-' : ' '); + switch (s.id.to_ulong()) { + case 0: + std::cout << 'a'; + break; + case 1: + std::cout << 'b'; + break; + case 2: + std::cout << 'c'; + break; + default: + throw std::runtime_error("Unexpected symbol codification."); + } +} + +void print(std::array const& a) { + for (auto const& s : a) { + print(s); + std::cout << ' '; + } +} + +// [ 1 0 0 ] +// [ 0 cos(alpha) sin(alpha) ] +// [ 0 -sin(alpha) cos(alpha) ] +template void Rx(std::array& v) { + T backup = v[1]; + v[1] = v[2]; + v[2] = -backup; +} + +// [ cos(beta) 0 -sin(beta) ] +// [ 0 1 0 ] +// [ sin(beta) 0 cos(beta) ] +template void Ry(std::array& v) { + T backup = v[0]; + v[0] = -v[2]; + v[2] = backup; +} + +// [ cos(gamma) sin(gamma) 0 ] +// [ -sin(gamma) cos(gamma) 0 ] +// [ 0 0 1 ] +template void Rz(std::array& v) { + T backup = v[0]; + v[0] = v[1]; + v[1] = -backup; +} + +void rotation_vector_mapping(std::array const& vector, std::array const& item) { + //TODO a goes to this position negated or not + // b goes to that ... + // c goes to ... +} + +void generate_rotations() { + // vector [a b c]^T is used as "canonical". + std::array const vector = [](){ + std::array vector; + vector.at(0).id = 0, vector.at(0).negative = false; + vector.at(1).id = 1, vector.at(1).negative = false; + vector.at(2).id = 2, vector.at(2).negative = false; + return vector; + }(); + + std::unordered_set, boost::hash>> Qed; + Qed.insert(vector); + std::queue> Q; + Q.push(vector); + auto g = [&Q, &Qed](auto const& v, std::function&)> R) { + auto w = v; + R(w); + if (!Qed.contains(w)) { + Q.push(w); + Qed.insert(w); + } + }; + while (!Q.empty()) { + std::array const v = Q.front(); + Q.pop(); + g(v, Rx); + g(v, Ry); + g(v, Rz); + } + for (auto const& item : Qed) { + print(item); + std::cout << '\n'; + rotation_vector_mapping(vector, item); + } + if (Qed.size() != 24) throw std::runtime_error("Unexpected #rotations."); +} + +int main() { + generate_rotations(); +} From 4570881d3db6a393a52a898171b99e78b630a2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sat, 21 Feb 2026 10:14:24 +0100 Subject: [PATCH 02/14] Build matrices mapping canonical to rotations --- adventofcode/2021/day/19/beacon_scanner.cpp | 59 +++++++++++++++------ 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 01e466d..112e53b 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -2,8 +2,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -18,6 +20,18 @@ struct symbol { bool operator==(symbol const& that) const { return id == that.id && negative == that.negative; } + bool operator==(char c) const { + switch (c) { + case 'a': + return id == std::bitset<2>(0); + case 'b': + return id == std::bitset<2>(1); + case 'c': + return id == std::bitset<2>(2); + default: + throw std::invalid_argument("Invalid character for symbol. It isn't one of a, b, or c."); + } + } }; std::size_t hash_value(symbol const& s) { @@ -48,6 +62,11 @@ void print(std::array const& a) { } } +void print(std::array, 3> matrix) { + for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) + std::cout << std::setw(2) << matrix.at(i).at(j) << (j == 2 ? "\n" : " "); +} + // [ 1 0 0 ] // [ 0 cos(alpha) sin(alpha) ] // [ 0 -sin(alpha) cos(alpha) ] @@ -75,15 +94,8 @@ template void Rz(std::array& v) { v[1] = -backup; } -void rotation_vector_mapping(std::array const& vector, std::array const& item) { - //TODO a goes to this position negated or not - // b goes to that ... - // c goes to ... -} - -void generate_rotations() { - // vector [a b c]^T is used as "canonical". - std::array const vector = [](){ +// vector [a b c]^T is used as "canonical". +std::array const vector = [](){ std::array vector; vector.at(0).id = 0, vector.at(0).negative = false; vector.at(1).id = 1, vector.at(1).negative = false; @@ -91,6 +103,7 @@ void generate_rotations() { return vector; }(); +auto generate_rotations() { std::unordered_set, boost::hash>> Qed; Qed.insert(vector); std::queue> Q; @@ -110,14 +123,30 @@ void generate_rotations() { g(v, Ry); g(v, Rz); } - for (auto const& item : Qed) { - print(item); - std::cout << '\n'; - rotation_vector_mapping(vector, item); - } if (Qed.size() != 24) throw std::runtime_error("Unexpected #rotations."); + return Qed; +} + +auto rotation_vector_mapping(std::array const& item) { + auto find_symbol_position = [](auto const& item, char c){ + for (int pos = 0; pos < 3; pos++) if (item.at(pos) == c) return pos; + throw std::runtime_error("Symbol not found."); + }; + + std::array, 3> matrix; + matrix.fill(std::array{0, 0, 0}); + for (int offset = 0; offset < 3; offset++) { + int const pos = find_symbol_position(item, 'a'+offset); + matrix.at(offset).at(pos) = item.at(pos).negative ? -1 : 1; + } + return matrix; } int main() { - generate_rotations(); + auto const rotations = generate_rotations(); + for (auto const& item : rotations) { + auto const matrix = rotation_vector_mapping(item); + std::cout << "To go from"; print(vector); std::cout << "to "; print(item); + std::cout << "\n"; print(matrix); + } } From 1a0dbebff938f6004e0fb5c6f4b7bfbc5f1b8705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Mon, 23 Feb 2026 04:20:24 +0100 Subject: [PATCH 03/14] Look for overlap between two scans --- adventofcode/2021/day/19/beacon_scanner.cpp | 69 +++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 112e53b..73a5fca 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -1,12 +1,17 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include #include +#include #include @@ -142,11 +147,67 @@ auto rotation_vector_mapping(std::array const& item) { return matrix; } +auto read_scan_report(std::string const& scan_report_fname) { + std::ifstream scan_file(scan_report_fname); + std::string line; + std::vector> scan_report; + for (;;) { + std::getline(scan_file, line); + if (line.empty()) break; + auto const p = line.find(','); + int const x = std::stoi(line.substr(0, p)); + auto const q = line.find(',', p+1); + int const y = std::stoi(line.substr(p+1, q-p)); + int const z = std::stoi(line.substr(q+1)); + scan_report.push_back({x, y, z}); + } + return scan_report; +} + int main() { auto const rotations = generate_rotations(); - for (auto const& item : rotations) { - auto const matrix = rotation_vector_mapping(item); - std::cout << "To go from"; print(vector); std::cout << "to "; print(item); - std::cout << "\n"; print(matrix); + std::vector> scan0 = read_scan_report("scan0.txt"); + std::vector> scan1 = read_scan_report("scan1.txt"); + + for (size_t i = 0; i < scan0.size(); i++) for (size_t j = 0; j < scan1.size(); j++) { + for (auto const& item : rotations) { + auto const matrix = rotation_vector_mapping(item); + // Apply matrix to scan1[j] + auto matmul = [&](int r, size_t idx1){ + int c = 0; + for (int k = 0; k < 3; k++) c += matrix.at(r).at(k) * scan1.at(idx1).at(k); + return c; + }; + auto const x1 = matmul(0, j); + auto const y1 = matmul(1, j); + auto const z1 = matmul(2, j); + // Compute shift from scan1[j] and scan0[i] + auto const dx = x1 - scan0.at(i).at(0); + auto const dy = y1 - scan0.at(i).at(1); + auto const dz = z1 - scan0.at(i).at(2); + // Assertion: + assert(scan0[i] == std::make_tuple(x1-dx, y1-dy, z1-dz)); + // Count the number of points in scan1 that after rotating and shifting + // are points in scan0 + std::flat_set> scan0set; + for (size_t ii = 0; ii < scan0.size(); ii++) { + if (ii == i) continue; + scan0set.insert(scan0.at(ii)); + } + int matches_count = 1; // starting from 1 because scan1[j]'s been placed at scan0[i] + for (size_t jj = 0; jj < scan1.size(); jj++) { + if (jj == j) continue; + auto const xjj = matmul(0, jj); + auto const yjj = matmul(1, jj); + auto const zjj = matmul(2, jj); + auto const p = std::make_tuple(xjj-dx, yjj-dy, zjj-dz); + if (scan0set.contains(p)) { + matches_count += 1; + scan0set.erase(p); + } + if (matches_count == 12) break; + } + if (matches_count == 12) std::cout << "Overlap found!\n"; + } } } From 6d7568f0afd08595c944e67430cef350bcf56ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Tue, 24 Feb 2026 15:39:16 +0100 Subject: [PATCH 04/14] Process input scans --- adventofcode/2021/day/19/beacon_scanner.cpp | 48 +++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 73a5fca..fd021a2 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -2,10 +2,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -147,12 +147,11 @@ auto rotation_vector_mapping(std::array const& item) { return matrix; } -auto read_scan_report(std::string const& scan_report_fname) { - std::ifstream scan_file(scan_report_fname); +auto read_scan_report(std::istream& input_stream) { std::string line; std::vector> scan_report; for (;;) { - std::getline(scan_file, line); + std::getline(input_stream, line); if (line.empty()) break; auto const p = line.find(','); int const x = std::stoi(line.substr(0, p)); @@ -164,12 +163,29 @@ auto read_scan_report(std::string const& scan_report_fname) { return scan_report; } +auto read_input() { + std::vector>> scans; + std::string line; + while (std::getline(std::cin, line)) { + //assert(line.substr(0, 12) == "--- scanner "); + scans.push_back(read_scan_report(std::cin)); + } + return scans; +} + int main() { auto const rotations = generate_rotations(); - std::vector> scan0 = read_scan_report("scan0.txt"); - std::vector> scan1 = read_scan_report("scan1.txt"); - for (size_t i = 0; i < scan0.size(); i++) for (size_t j = 0; j < scan1.size(); j++) { + auto const scans = read_input(); + + for (size_t scan_idx_i = 0; scan_idx_i < scans.size(); scan_idx_i++) { + for (size_t scan_idx_j = scan_idx_i + 1; scan_idx_j < scans.size(); scan_idx_j++) { + + auto const& scan0 = scans.at(scan_idx_i); + auto const& scan1 = scans.at(scan_idx_j); + + bool overlap_found = false; + for (size_t i = 0; i < scan0.size() && !overlap_found; i++) for (size_t j = 0; j < scan1.size() && !overlap_found; j++) { for (auto const& item : rotations) { auto const matrix = rotation_vector_mapping(item); // Apply matrix to scan1[j] @@ -195,6 +211,8 @@ int main() { scan0set.insert(scan0.at(ii)); } int matches_count = 1; // starting from 1 because scan1[j]'s been placed at scan0[i] + std::vector> matches; + matches.push_back(scan0.at(i)); for (size_t jj = 0; jj < scan1.size(); jj++) { if (jj == j) continue; auto const xjj = matmul(0, jj); @@ -204,10 +222,24 @@ int main() { if (scan0set.contains(p)) { matches_count += 1; scan0set.erase(p); + matches.push_back(p); } if (matches_count == 12) break; } - if (matches_count == 12) std::cout << "Overlap found!\n"; + if (matches_count == 12) { + std::println("{:2} overlaps with {:2}", scan_idx_i, scan_idx_j); + overlap_found = true; + /* + for (auto const& match : matches) { + std::print(" {}\n", match); + } + */ + break; + } } } + + } + } +} } From af77ac662f4a6f76a5e19f9e75a24a89e6ff1de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Tue, 24 Feb 2026 23:10:25 +0100 Subject: [PATCH 05/14] store transformations; checks on sample input; check single connected component --- adventofcode/2021/day/19/beacon_scanner.cpp | 54 +++++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index fd021a2..3c455a4 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -39,6 +39,11 @@ struct symbol { } }; +struct transformation { + std::array, 3> rotation; + std::array translation; +}; + std::size_t hash_value(symbol const& s) { return s.id.to_ullong() ^ s.negative; } @@ -173,11 +178,16 @@ auto read_input() { return scans; } +int const mininum_overlapping_beacons = 12; + int main() { auto const rotations = generate_rotations(); auto const scans = read_input(); + std::unordered_map> A; + std::unordered_map> B; + for (size_t scan_idx_i = 0; scan_idx_i < scans.size(); scan_idx_i++) { for (size_t scan_idx_j = scan_idx_i + 1; scan_idx_j < scans.size(); scan_idx_j++) { @@ -211,8 +221,8 @@ int main() { scan0set.insert(scan0.at(ii)); } int matches_count = 1; // starting from 1 because scan1[j]'s been placed at scan0[i] - std::vector> matches; - matches.push_back(scan0.at(i)); + std::vector, std::tuple>> matches; + matches.emplace_back(scan0.at(i), scan1.at(j)); for (size_t jj = 0; jj < scan1.size(); jj++) { if (jj == j) continue; auto const xjj = matmul(0, jj); @@ -222,18 +232,25 @@ int main() { if (scan0set.contains(p)) { matches_count += 1; scan0set.erase(p); - matches.push_back(p); + matches.emplace_back(p, scan1.at(jj)); } - if (matches_count == 12) break; + if (matches_count == mininum_overlapping_beacons) break; } - if (matches_count == 12) { - std::println("{:2} overlaps with {:2}", scan_idx_i, scan_idx_j); + if (matches_count == mininum_overlapping_beacons) { overlap_found = true; - /* - for (auto const& match : matches) { - std::print(" {}\n", match); + A[scan_idx_i][scan_idx_j] = {matrix, {dx, dy, dz}}; + B[scan_idx_i].push_back(scan_idx_j); + B[scan_idx_j].push_back(scan_idx_i); + std::println("{} -> {}:", scan_idx_i, scan_idx_j); + std::println("{}", A[scan_idx_i][scan_idx_j].rotation); + std::println("{}\n", A[scan_idx_i][scan_idx_j].translation); + if (scan_idx_i == 0 && scan_idx_j == 1) { + std::println("Beacons relative to scanner 0:"); + for (auto const& pq : matches) std::println(" {}", pq.first); + std::println("Beacons relative to scanner 1:"); + for (auto const& pq : matches) std::println(" {}", pq.second); + std::println("Scanner 1 is at {}.", A[0][1].translation); // appears negated } - */ break; } } @@ -241,5 +258,22 @@ int main() { } } + + // Is there more than one connected component? + { + std::unordered_set c; + std::queue d; + c.insert(0); + d.push(0); + while (!d.empty()) { + int const n = d.front(); + d.pop(); + for (int const m : B[n]) if (!c.contains(m)) { + c.insert(m); + d.push(m); + } + } + std::println("scans size: {}, #CC: {}", scans.size(), c.size()); + } } } From 792ce1715302737b42ffbfd31467bfce7996ea3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sat, 28 Feb 2026 15:19:37 +0100 Subject: [PATCH 06/14] WiP: find coordinates of every scanner (other than 0) wrt t0 scanner 0; refactor --- adventofcode/2021/day/19/beacon_scanner.cpp | 160 +++++++++++++++----- 1 file changed, 121 insertions(+), 39 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 3c455a4..8e77b26 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -39,9 +39,17 @@ struct symbol { } }; +namespace math { + +constexpr int dim = 3; +template using vector = std::array; +template using matrix = std::array, dim>; + +}; + struct transformation { - std::array, 3> rotation; - std::array translation; + math::matrix rotation; + math::vector translation; }; std::size_t hash_value(symbol const& s) { @@ -65,16 +73,16 @@ void print(symbol const& s) { } } -void print(std::array const& a) { +void print(math::vector const& a) { for (auto const& s : a) { print(s); std::cout << ' '; } } -void print(std::array, 3> matrix) { +void print(math::matrix A) { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) - std::cout << std::setw(2) << matrix.at(i).at(j) << (j == 2 ? "\n" : " "); + std::cout << std::setw(2) << A.at(i).at(j) << (j == 2 ? "\n" : " "); } // [ 1 0 0 ] @@ -104,20 +112,20 @@ template void Rz(std::array& v) { v[1] = -backup; } -// vector [a b c]^T is used as "canonical". -std::array const vector = [](){ - std::array vector; - vector.at(0).id = 0, vector.at(0).negative = false; - vector.at(1).id = 1, vector.at(1).negative = false; - vector.at(2).id = 2, vector.at(2).negative = false; - return vector; +// symbolic vector [a b c]^T +std::array const v = [](){ + std::array v; + v.at(0).id = 0, v.at(0).negative = false; + v.at(1).id = 1, v.at(1).negative = false; + v.at(2).id = 2, v.at(2).negative = false; + return v; }(); auto generate_rotations() { std::unordered_set, boost::hash>> Qed; - Qed.insert(vector); + Qed.insert(v); std::queue> Q; - Q.push(vector); + Q.push(v); auto g = [&Q, &Qed](auto const& v, std::function&)> R) { auto w = v; R(w); @@ -143,13 +151,13 @@ auto rotation_vector_mapping(std::array const& item) { throw std::runtime_error("Symbol not found."); }; - std::array, 3> matrix; - matrix.fill(std::array{0, 0, 0}); + math::matrix rotation; + rotation.fill(std::array{0, 0, 0}); for (int offset = 0; offset < 3; offset++) { int const pos = find_symbol_position(item, 'a'+offset); - matrix.at(offset).at(pos) = item.at(pos).negative ? -1 : 1; + rotation.at(offset).at(pos) = item.at(pos).negative ? -1 : 1; } - return matrix; + return rotation; } auto read_scan_report(std::istream& input_stream) { @@ -180,13 +188,22 @@ auto read_input() { int const mininum_overlapping_beacons = 12; +auto operator*(math::matrix const& A, math::vector const& v) { + auto matmul = [A, v](int r){ + int c = 0; + for (int k = 0; k < 3; k++) c += A.at(r).at(k) * v.at(k); + return c; + }; + return std::make_tuple(matmul(0), matmul(1), matmul(2)); +} + int main() { auto const rotations = generate_rotations(); auto const scans = read_input(); std::unordered_map> A; - std::unordered_map> B; + std::unordered_map> neighbors; for (size_t scan_idx_i = 0; scan_idx_i < scans.size(); scan_idx_i++) { for (size_t scan_idx_j = scan_idx_i + 1; scan_idx_j < scans.size(); scan_idx_j++) { @@ -197,16 +214,9 @@ int main() { bool overlap_found = false; for (size_t i = 0; i < scan0.size() && !overlap_found; i++) for (size_t j = 0; j < scan1.size() && !overlap_found; j++) { for (auto const& item : rotations) { - auto const matrix = rotation_vector_mapping(item); - // Apply matrix to scan1[j] - auto matmul = [&](int r, size_t idx1){ - int c = 0; - for (int k = 0; k < 3; k++) c += matrix.at(r).at(k) * scan1.at(idx1).at(k); - return c; - }; - auto const x1 = matmul(0, j); - auto const y1 = matmul(1, j); - auto const z1 = matmul(2, j); + auto const rotation = rotation_vector_mapping(item); + // Apply rotation to scan1[j] + auto const [x1, y1, z1] = rotation * scan1.at(j); // Compute shift from scan1[j] and scan0[i] auto const dx = x1 - scan0.at(i).at(0); auto const dy = y1 - scan0.at(i).at(1); @@ -225,9 +235,7 @@ int main() { matches.emplace_back(scan0.at(i), scan1.at(j)); for (size_t jj = 0; jj < scan1.size(); jj++) { if (jj == j) continue; - auto const xjj = matmul(0, jj); - auto const yjj = matmul(1, jj); - auto const zjj = matmul(2, jj); + auto const [xjj, yjj, zjj] = rotation * scan1.at(jj); auto const p = std::make_tuple(xjj-dx, yjj-dy, zjj-dz); if (scan0set.contains(p)) { matches_count += 1; @@ -238,18 +246,18 @@ int main() { } if (matches_count == mininum_overlapping_beacons) { overlap_found = true; - A[scan_idx_i][scan_idx_j] = {matrix, {dx, dy, dz}}; - B[scan_idx_i].push_back(scan_idx_j); - B[scan_idx_j].push_back(scan_idx_i); + A[scan_idx_i][scan_idx_j] = {rotation, {-dx, -dy, -dz}}; + neighbors[scan_idx_i].push_back(scan_idx_j); + neighbors[scan_idx_j].push_back(scan_idx_i); std::println("{} -> {}:", scan_idx_i, scan_idx_j); - std::println("{}", A[scan_idx_i][scan_idx_j].rotation); - std::println("{}\n", A[scan_idx_i][scan_idx_j].translation); if (scan_idx_i == 0 && scan_idx_j == 1) { + /* std::println("Beacons relative to scanner 0:"); for (auto const& pq : matches) std::println(" {}", pq.first); std::println("Beacons relative to scanner 1:"); for (auto const& pq : matches) std::println(" {}", pq.second); - std::println("Scanner 1 is at {}.", A[0][1].translation); // appears negated + */ + std::println("Scanner 1 is at {}", A[0][1].translation); } break; } @@ -260,6 +268,7 @@ int main() { } // Is there more than one connected component? + /* { std::unordered_set c; std::queue d; @@ -268,12 +277,85 @@ int main() { while (!d.empty()) { int const n = d.front(); d.pop(); - for (int const m : B[n]) if (!c.contains(m)) { + for (int const m : neighbors[n]) if (!c.contains(m)) { c.insert(m); d.push(m); } } std::println("scans size: {}, #CC: {}", scans.size(), c.size()); } + std::println(); + */ + + // Paths to scan0: + { + for (size_t scan_idx = 1; scan_idx < scans.size(); scan_idx++) { + std::queue>> Q; + Q.emplace(scan_idx, std::vector{}); + std::unordered_set Qed; + Qed.insert(scan_idx); + bool scan0_found = false; + while (!Q.empty()) { + auto [node, path] = Q.front(); + Q.pop(); + for (int const neighbor : neighbors[node]) if (!Qed.contains(neighbor)) { + if (neighbor == 0) { + scan0_found = true; + std::print("{} -> ", scan_idx); + for (int const intermediate_node : path) { + std::print("{} -> ", intermediate_node); + } + std::println("0"); + + // Validating on sample input: + int const scan_idx_inspected = 2; + if (scan_idx == scan_idx_inspected) { + math::vector p{0,0,0}; + int from = scan_idx_inspected; + for (size_t path_idx = 0; path_idx <= path.size(); path_idx++) { + int const to = path_idx == path.size() ? 0 : path[path_idx]; + std::print(" From {} to {}: ", from, to); + if (A.contains(from) && A.at(from).contains(to)) { + std::println("direct"); + //std::array, 3> inverse; + //for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) + // inverse[r][c] = A[from][to].rotation[c][r]; + // rotate + //auto const [x, y, z] = matvecmul(inverse, p); + //auto const [x, y, z] = matvecmul(A[from][to].rotation, p); + auto const [x, y, z] = A[from][to].rotation * p; + p[0] = x, p[1] = y, p[2] = z; + // translate + for (int c = 0; c < 3; c++) { + p[c] += A[from][to].translation[c]; + } + } else { + assert(A.contains(to) && A[to].contains(from)); + std::println("inverse"); + // rotate + //auto const [x, y, z] = matvecmul(inverse, p); + //auto const [x, y, z] = matvecmul(A[to][from].rotation, p); + auto const [x, y, z] = A[to][from].rotation * p; + p[0] = x, p[1] = y, p[2] = z; + // translate + for (int c = 0; c < 3; c++) { + p[c] += A[to][from].translation[c]; + } + } + from = to; + } + std::println("Scanner {} is at {}", scan_idx, p); + } + + break; + } else { + path.push_back(neighbor); + Qed.insert(neighbor); + Q.emplace(neighbor, path); + } + } + } + } + } } } From b50d79784185ec31ddffffaa4e34284402e5685c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sun, 1 Mar 2026 00:20:54 +0100 Subject: [PATCH 07/14] debugging --- adventofcode/2021/day/19/beacon_scanner.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 8e77b26..e03cda2 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -308,10 +308,9 @@ int main() { std::println("0"); // Validating on sample input: - int const scan_idx_inspected = 2; - if (scan_idx == scan_idx_inspected) { + { math::vector p{0,0,0}; - int from = scan_idx_inspected; + int from = scan_idx; for (size_t path_idx = 0; path_idx <= path.size(); path_idx++) { int const to = path_idx == path.size() ? 0 : path[path_idx]; std::print(" From {} to {}: ", from, to); From ae62b4ff2897891fba8e506d2f593f25ca53812c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sun, 1 Mar 2026 01:32:38 +0100 Subject: [PATCH 08/14] fix transformations and refactor refactor: matrix doesn't need to be a template --- adventofcode/2021/day/19/beacon_scanner.cpp | 29 +++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index e03cda2..9b55f86 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -43,12 +43,12 @@ namespace math { constexpr int dim = 3; template using vector = std::array; -template using matrix = std::array, dim>; +using matrix = std::array, dim>; }; struct transformation { - math::matrix rotation; + math::matrix rotation; math::vector translation; }; @@ -80,7 +80,7 @@ void print(math::vector const& a) { } } -void print(math::matrix A) { +void print(math::matrix A) { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) std::cout << std::setw(2) << A.at(i).at(j) << (j == 2 ? "\n" : " "); } @@ -151,7 +151,7 @@ auto rotation_vector_mapping(std::array const& item) { throw std::runtime_error("Symbol not found."); }; - math::matrix rotation; + math::matrix rotation; rotation.fill(std::array{0, 0, 0}); for (int offset = 0; offset < 3; offset++) { int const pos = find_symbol_position(item, 'a'+offset); @@ -188,7 +188,7 @@ auto read_input() { int const mininum_overlapping_beacons = 12; -auto operator*(math::matrix const& A, math::vector const& v) { +auto operator*(math::matrix const& A, math::vector const& v) { auto matmul = [A, v](int r){ int c = 0; for (int k = 0; k < 3; k++) c += A.at(r).at(k) * v.at(k); @@ -316,24 +316,21 @@ int main() { std::print(" From {} to {}: ", from, to); if (A.contains(from) && A.at(from).contains(to)) { std::println("direct"); - //std::array, 3> inverse; - //for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) - // inverse[r][c] = A[from][to].rotation[c][r]; - // rotate - //auto const [x, y, z] = matvecmul(inverse, p); - //auto const [x, y, z] = matvecmul(A[from][to].rotation, p); - auto const [x, y, z] = A[from][to].rotation * p; - p[0] = x, p[1] = y, p[2] = z; // translate for (int c = 0; c < 3; c++) { - p[c] += A[from][to].translation[c]; + p[c] -= A[from][to].translation[c]; + } + math::matrix inverse; + for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) { + inverse[r][c] = A[from][to].rotation[c][r]; } + // rotate + auto const [x, y, z] = A[from][to].rotation * p; + p[0] = x, p[1] = y, p[2] = z; } else { assert(A.contains(to) && A[to].contains(from)); std::println("inverse"); // rotate - //auto const [x, y, z] = matvecmul(inverse, p); - //auto const [x, y, z] = matvecmul(A[to][from].rotation, p); auto const [x, y, z] = A[to][from].rotation * p; p[0] = x, p[1] = y, p[2] = z; // translate From 926c10e4dab2cb7ae7dbffd64e23b933b98a8af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sun, 1 Mar 2026 04:14:47 +0100 Subject: [PATCH 09/14] :bug: --- adventofcode/2021/day/19/beacon_scanner.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 9b55f86..9aae6a9 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -348,6 +348,7 @@ int main() { path.push_back(neighbor); Qed.insert(neighbor); Q.emplace(neighbor, path); + path.pop_back(); } } } From 409eca2eb35e3bee285aff792fb6f716752bc054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Tue, 10 Mar 2026 01:09:32 +0100 Subject: [PATCH 10/14] add transformation visualizer --- .../19/transformation_visualizer/README.md | 6 + .../day/19/transformation_visualizer/plug.c | 264 ++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 adventofcode/2021/day/19/transformation_visualizer/README.md create mode 100644 adventofcode/2021/day/19/transformation_visualizer/plug.c diff --git a/adventofcode/2021/day/19/transformation_visualizer/README.md b/adventofcode/2021/day/19/transformation_visualizer/README.md new file mode 100644 index 0000000..8d35295 --- /dev/null +++ b/adventofcode/2021/day/19/transformation_visualizer/README.md @@ -0,0 +1,6 @@ +plug_update + draw_frame(&plug->reference_frame0) + +master_sequence(arena) + scene_transformation_visualizer(arena) + task_move_scalar(arena, &plug->reference_frame0 diff --git a/adventofcode/2021/day/19/transformation_visualizer/plug.c b/adventofcode/2021/day/19/transformation_visualizer/plug.c new file mode 100644 index 0000000..fbc3171 --- /dev/null +++ b/adventofcode/2021/day/19/transformation_visualizer/plug.c @@ -0,0 +1,264 @@ +#include +#include +#include + +#include +#include + +#include "nob.h" +#include "env.h" +#include "interpolators.h" +#include "tasks.h" +#include "plug.h" + +#define PLUG(name, ret, ...) ret name(__VA_ARGS__); +LIST_OF_PLUGS +#undef PLUG + +// --- DATA STRUCTURES --- + +typedef struct { + Vector3 origin; + Vector3 i_hat; + Vector3 j_hat; + Vector3 k_hat; + float opacity; +} ReferenceFrame; + +typedef struct { + size_t size; + Arena arena_state; + Arena arena_assets; + bool finished; + + // Global Camera + Camera3D camera; + + // Scene State + int current_scene_index; + Task task; + + // Visual Elements + ReferenceFrame f0; // For TransformationVisualizer + //ReferenceFrame f1; // For MatrixTransformScene + //ReferenceFrame fa; // For CompareFramesScene + //ReferenceFrame fb; // For CompareFramesScene + +} Plug; + +static Plug *p = NULL; + +// --- HELPERS --- + +static ReferenceFrame default_frame(Vector3 origin) { + return (ReferenceFrame){ + .origin = origin, + .i_hat = (Vector3){1.0f, 0.0f, 0.0f}, + .j_hat = (Vector3){0.0f, 1.0f, 0.0f}, + .k_hat = (Vector3){0.0f, 0.0f, 1.0f}, + .opacity = 0.0f // Start invisible + }; +} + +static void draw_vector(Vector3 start, Vector3 vec, Color color, float opacity) { + Vector3 end = Vector3Add(start, vec); + Color c = ColorAlpha(color, opacity); + DrawLine3D(start, end, c); + DrawSphere(end, 0.05f, c); // Tip +} + +static void draw_frame(ReferenceFrame *f) { + if (f->opacity <= 0.01f) return; + + Color color_x = ColorAlpha(RED, f->opacity); + Color color_y = ColorAlpha(GREEN, f->opacity); + Color color_z = ColorAlpha(BLUE, f->opacity); + Color color_origin = ColorAlpha(WHITE, f->opacity); + + draw_vector(f->origin, f->i_hat, color_x, f->opacity); + draw_vector(f->origin, f->j_hat, color_y, f->opacity); + draw_vector(f->origin, f->k_hat, color_z, f->opacity); + DrawSphere(f->origin, 0.05f, color_origin); +} + +// --- TASKS --- + +static Task scene_transformation_visualizer(Arena *a) { + ReferenceFrame *f0 = &p->f0; + *f0 = default_frame((Vector3){0,0,0}); + + // Rotation Matrix: 90 deg around Z + /* + Vector3 rot_i = (Vector3){0, 1, 0}; + Vector3 rot_j = (Vector3){-1, 0, 0}; + Vector3 rot_k = (Vector3){0, 0, 1}; + */ + Vector3 rot_i = (Vector3){1, 0, 0}; + Vector3 rot_j = (Vector3){0, 1, 0}; + Vector3 rot_k = (Vector3){0, 0, 1}; + + Vector3 shift_val = (Vector3){2, 0, 0}; + Vector3 final_origin = Vector3Add(f0->origin, shift_val); + + return task_seq(a, + task_move_scalar(a, &f0->opacity, 1.0f, 1.0f, FUNC_SMOOTHSTEP), + task_wait(a, 0.5f), + task_group(a, + task_move_vec3(a, &f0->i_hat, rot_i, 1.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &f0->j_hat, rot_j, 1.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &f0->k_hat, rot_k, 1.0f, FUNC_SMOOTHSTEP) + ), + task_move_vec3(a, &f0->origin, final_origin, 1.0f, FUNC_SMOOTHSTEP), + task_wait(a, 2.0f) + ); +} + +/* +static Task scene_matrix_transform(Arena *a) { + ReferenceFrame *f1 = &p->f1; + *f1 = default_frame((Vector3){0,0,0}); + + // Rotation Matrix: 90 deg around Z + Vector3 target_i = (Vector3){0, 1, 0}; + Vector3 target_j = (Vector3){-1, 0, 0}; + Vector3 target_k = (Vector3){0, 0, 1}; + + Vector3 translation = (Vector3){3, 2, 1}; + Vector3 final_origin = Vector3Add(f1->origin, translation); + + return task_seq(a, + task_move_scalar(a, &f1->opacity, 1.0f, 1.0f, FUNC_SMOOTHSTEP), + task_wait(a, 0.5f), + task_group(a, + task_move_vec3(a, &f1->i_hat, target_i, 2.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &f1->j_hat, target_j, 2.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &f1->k_hat, target_k, 2.0f, FUNC_SMOOTHSTEP) + ), + task_wait(a, 0.5f), + task_move_vec3(a, &f1->origin, final_origin, 2.0f, FUNC_SMOOTHSTEP), + task_wait(a, 2.0f) + ); +} +*/ + +/* +static Task scene_compare_frames(Arena *a) { + ReferenceFrame *fa = &p->fa; + ReferenceFrame *fb = &p->fb; + + Vector3 pos_a = (Vector3){0,0,0}; + Vector3 pos_b = (Vector3){2,1,0}; + + *fa = default_frame(pos_a); + *fb = default_frame(pos_b); + + // Rotation Matrix: 90 deg around Z + Vector3 target_i = (Vector3){0, 1, 0}; + Vector3 target_j = (Vector3){-1, 0, 0}; + Vector3 target_k = (Vector3){0, 0, 1}; + + fb->i_hat = target_i; + fb->j_hat = target_j; + fb->k_hat = target_k; + + return task_seq(a, + task_move_scalar(a, &fa->opacity, 1.0f, 1.0f, FUNC_SMOOTHSTEP), + task_wait(a, 0.5f), + task_move_scalar(a, &fb->opacity, 0.3f, 1.0f, FUNC_SMOOTHSTEP), + task_wait(a, 0.5f), + task_group(a, + task_move_vec3(a, &fa->origin, pos_b, 3.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &fa->i_hat, target_i, 3.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &fa->j_hat, target_j, 3.0f, FUNC_SMOOTHSTEP), + task_move_vec3(a, &fa->k_hat, target_k, 3.0f, FUNC_SMOOTHSTEP) + ), + task_wait(a, 2.0f) + ); +} +*/ + +static Task master_sequence(Arena *a) { + return task_seq(a, + scene_transformation_visualizer(a), + task_move_scalar(a, &p->f0.opacity, 0.0f, 0.5f, FUNC_SMOOTHSTEP)/*, + scene_matrix_transform(a), + task_move_scalar(a, &p->f1.opacity, 0.0f, 0.5f, FUNC_SMOOTHSTEP), + scene_compare_frames(a), + task_move_scalar(a, &p->fa.opacity, 0.0f, 0.5f, FUNC_SMOOTHSTEP), + task_move_scalar(a, &p->fb.opacity, 0.0f, 0.5f, FUNC_SMOOTHSTEP)*/ + ); +} + +// --- PLUG IMPL --- + +static void load_assets(void) +{ + arena_reset(&p->arena_assets); + task_vtable_rebuild(&p->arena_assets); + TraceLog(LOG_INFO, "Transformation Visualizer: Assets and VTable loaded"); +} + +void plug_init(void) +{ + p = malloc(sizeof(*p)); + assert(p != NULL); + memset(p, 0, sizeof(*p)); + p->size = sizeof(*p); + + p->camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; + p->camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + p->camera.up = (Vector3){ 0.0f, 0.0f, 1.0f }; + p->camera.fovy = 45.0f; + p->camera.projection = CAMERA_PERSPECTIVE; + + load_assets(); + plug_reset(); +} + +void *plug_pre_reload(void) +{ + return p; +} + +void plug_post_reload(void *state) +{ + p = state; + if (p->size < sizeof(*p)) { + p = realloc(p, sizeof(*p)); + p->size = sizeof(*p); + } + load_assets(); +} + +void plug_update(Env env) +{ + p->finished = task_update(p->task, env); + ClearBackground(BLACK); + BeginMode3D(p->camera); + DrawGrid(10, 1.0f); + draw_frame(&p->f0); + //draw_frame(&p->f1); + //draw_frame(&p->fa); + //draw_frame(&p->fb); + EndMode3D(); +} + +void plug_reset(void) +{ + arena_reset(&p->arena_state); + p->f0 = default_frame((Vector3){0,0,0}); + //p->f1 = default_frame((Vector3){0,0,0}); + //p->fa = default_frame((Vector3){0,0,0}); + //p->fb = default_frame((Vector3){0,0,0}); + p->task = master_sequence(&p->arena_state); + p->finished = false; +} + +bool plug_finished(void) +{ + return p->finished; +} + +#define ARENA_IMPLEMENTATION +#include "arena.h" +#include "tasks.c" From ac75594de480352bb4c23831e11aa51ff36b30ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Wed, 11 Mar 2026 14:06:54 +0100 Subject: [PATCH 11/14] :bug: :bug: and remove unused variable --- adventofcode/2021/day/19/beacon_scanner.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 9aae6a9..01999c7 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -294,13 +294,11 @@ int main() { Q.emplace(scan_idx, std::vector{}); std::unordered_set Qed; Qed.insert(scan_idx); - bool scan0_found = false; while (!Q.empty()) { auto [node, path] = Q.front(); Q.pop(); for (int const neighbor : neighbors[node]) if (!Qed.contains(neighbor)) { if (neighbor == 0) { - scan0_found = true; std::print("{} -> ", scan_idx); for (int const intermediate_node : path) { std::print("{} -> ", intermediate_node); @@ -325,7 +323,7 @@ int main() { inverse[r][c] = A[from][to].rotation[c][r]; } // rotate - auto const [x, y, z] = A[from][to].rotation * p; + auto const [x, y, z] = inverse * p; p[0] = x, p[1] = y, p[2] = z; } else { assert(A.contains(to) && A[to].contains(from)); From 47beb7d2b7dda0aeabb51eeb3b3ccedbec8dd843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Wed, 11 Mar 2026 14:09:09 +0100 Subject: [PATCH 12/14] Finish! --- adventofcode/2021/day/19/beacon_scanner.cpp | 59 ++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 01999c7..3a0bff9 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -162,7 +162,7 @@ auto rotation_vector_mapping(std::array const& item) { auto read_scan_report(std::istream& input_stream) { std::string line; - std::vector> scan_report; + std::vector> scan_report; for (;;) { std::getline(input_stream, line); if (line.empty()) break; @@ -177,7 +177,7 @@ auto read_scan_report(std::istream& input_stream) { } auto read_input() { - std::vector>> scans; + std::vector>> scans; std::string line; while (std::getline(std::cin, line)) { //assert(line.substr(0, 12) == "--- scanner "); @@ -287,6 +287,13 @@ int main() { std::println(); */ + std::flat_set> pointsAt0; + for (auto const& p : scans.at(0)) { + pointsAt0.emplace(p.at(0), p.at(1), p.at(2)); + } + + std::vector> scanners_positions(scans.size()); + scanners_positions.at(0) = {0, 0, 0}; // Paths to scan0: { for (size_t scan_idx = 1; scan_idx < scans.size(); scan_idx++) { @@ -339,6 +346,41 @@ int main() { from = to; } std::println("Scanner {} is at {}", scan_idx, p); + scanners_positions.at(scan_idx) = p; + } + + { + for (auto const& pconst : scans.at(scan_idx)) { + auto p = pconst; + int from = scan_idx; + for (size_t path_idx = 0; path_idx <= path.size(); path_idx++) { + int const to = path_idx == path.size() ? 0 : path[path_idx]; + if (A.contains(from) && A.at(from).contains(to)) { + // translate + for (int c = 0; c < 3; c++) { + p[c] -= A[from][to].translation[c]; + } + math::matrix inverse; + for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) { + inverse[r][c] = A[from][to].rotation[c][r]; + } + // rotate + auto const [x, y, z] = inverse * p; + p[0] = x, p[1] = y, p[2] = z; + } else { + assert(A.contains(to) && A[to].contains(from)); + // rotate + auto const [x, y, z] = A[to][from].rotation * p; + p[0] = x, p[1] = y, p[2] = z; + // translate + for (int c = 0; c < 3; c++) { + p[c] += A[to][from].translation[c]; + } + } + from = to; + } + pointsAt0.emplace(p.at(0), p.at(1), p.at(2)); + } } break; @@ -351,6 +393,19 @@ int main() { } } } + std::println("In total, there are {} beacons.", pointsAt0.size()); + //for (auto const& point : pointsAt0) std::println("{}", point); + } + + int part_two_ans = 0; + for (size_t scanner_idx_i = 0; scanner_idx_i < scanners_positions.size(); scanner_idx_i++) { + for (size_t scanner_idx_j = scanner_idx_i+1; scanner_idx_j < scanners_positions.size(); scanner_idx_j++) { + part_two_ans = std::max(part_two_ans, + std::abs(scanners_positions.at(scanner_idx_i).at(0) - scanners_positions.at(scanner_idx_j).at(0)) + + std::abs(scanners_positions.at(scanner_idx_i).at(1) - scanners_positions.at(scanner_idx_j).at(1)) + + std::abs(scanners_positions.at(scanner_idx_i).at(2) - scanners_positions.at(scanner_idx_j).at(2))); + } } + std::println("In total, they are {} units apart.", part_two_ans); } } From 05f5b2d55095ac54f74e695056544f870424b9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Fri, 20 Mar 2026 11:39:31 +0100 Subject: [PATCH 13/14] Fix conversion warnings --- adventofcode/2021/day/19/beacon_scanner.cpp | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index 3a0bff9..fd1f397 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -154,7 +154,7 @@ auto rotation_vector_mapping(std::array const& item) { math::matrix rotation; rotation.fill(std::array{0, 0, 0}); for (int offset = 0; offset < 3; offset++) { - int const pos = find_symbol_position(item, 'a'+offset); + int const pos = find_symbol_position(item, 'a'+static_cast(offset)); rotation.at(offset).at(pos) = item.at(pos).negative ? -1 : 1; } return rotation; @@ -202,8 +202,8 @@ int main() { auto const scans = read_input(); - std::unordered_map> A; - std::unordered_map> neighbors; + std::unordered_map> A; + std::unordered_map> neighbors; for (size_t scan_idx_i = 0; scan_idx_i < scans.size(); scan_idx_i++) { for (size_t scan_idx_j = scan_idx_i + 1; scan_idx_j < scans.size(); scan_idx_j++) { @@ -297,17 +297,17 @@ int main() { // Paths to scan0: { for (size_t scan_idx = 1; scan_idx < scans.size(); scan_idx++) { - std::queue>> Q; - Q.emplace(scan_idx, std::vector{}); - std::unordered_set Qed; + std::queue>> Q; + Q.emplace(scan_idx, std::vector{}); + std::unordered_set Qed; Qed.insert(scan_idx); while (!Q.empty()) { auto [node, path] = Q.front(); Q.pop(); - for (int const neighbor : neighbors[node]) if (!Qed.contains(neighbor)) { + for (auto const neighbor : neighbors[node]) if (!Qed.contains(neighbor)) { if (neighbor == 0) { std::print("{} -> ", scan_idx); - for (int const intermediate_node : path) { + for (auto const intermediate_node : path) { std::print("{} -> ", intermediate_node); } std::println("0"); @@ -315,9 +315,9 @@ int main() { // Validating on sample input: { math::vector p{0,0,0}; - int from = scan_idx; + auto from = scan_idx; for (size_t path_idx = 0; path_idx <= path.size(); path_idx++) { - int const to = path_idx == path.size() ? 0 : path[path_idx]; + auto const to = path_idx == path.size() ? 0 : path[path_idx]; std::print(" From {} to {}: ", from, to); if (A.contains(from) && A.at(from).contains(to)) { std::println("direct"); @@ -352,9 +352,9 @@ int main() { { for (auto const& pconst : scans.at(scan_idx)) { auto p = pconst; - int from = scan_idx; + auto from = scan_idx; for (size_t path_idx = 0; path_idx <= path.size(); path_idx++) { - int const to = path_idx == path.size() ? 0 : path[path_idx]; + auto const to = path_idx == path.size() ? 0 : path[path_idx]; if (A.contains(from) && A.at(from).contains(to)) { // translate for (int c = 0; c < 3; c++) { From 0c40023861023c697010dd1291241d4f6bcafdc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9?= Date: Sun, 22 Mar 2026 05:35:51 +0100 Subject: [PATCH 14/14] Use boost unordered_flat_set --- adventofcode/2021/day/19/beacon_scanner.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/adventofcode/2021/day/19/beacon_scanner.cpp b/adventofcode/2021/day/19/beacon_scanner.cpp index fd1f397..521d367 100644 --- a/adventofcode/2021/day/19/beacon_scanner.cpp +++ b/adventofcode/2021/day/19/beacon_scanner.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -10,10 +9,10 @@ #include #include #include -#include #include #include +#include struct symbol { std::bitset<2> id; @@ -122,7 +121,7 @@ std::array const v = [](){ }(); auto generate_rotations() { - std::unordered_set, boost::hash>> Qed; + boost::unordered::unordered_flat_set> Qed; Qed.insert(v); std::queue> Q; Q.push(v); @@ -225,7 +224,7 @@ int main() { assert(scan0[i] == std::make_tuple(x1-dx, y1-dy, z1-dz)); // Count the number of points in scan1 that after rotating and shifting // are points in scan0 - std::flat_set> scan0set; + boost::unordered::unordered_flat_set> scan0set; for (size_t ii = 0; ii < scan0.size(); ii++) { if (ii == i) continue; scan0set.insert(scan0.at(ii)); @@ -287,10 +286,8 @@ int main() { std::println(); */ - std::flat_set> pointsAt0; - for (auto const& p : scans.at(0)) { - pointsAt0.emplace(p.at(0), p.at(1), p.at(2)); - } + boost::unordered::unordered_flat_set> pointsAt0; + for (auto const& p : scans.at(0)) pointsAt0.emplace(p.at(0), p.at(1), p.at(2)); std::vector> scanners_positions(scans.size()); scanners_positions.at(0) = {0, 0, 0}; @@ -299,7 +296,7 @@ int main() { for (size_t scan_idx = 1; scan_idx < scans.size(); scan_idx++) { std::queue>> Q; Q.emplace(scan_idx, std::vector{}); - std::unordered_set Qed; + boost::unordered::unordered_flat_set Qed; Qed.insert(scan_idx); while (!Q.empty()) { auto [node, path] = Q.front(); @@ -394,7 +391,6 @@ int main() { } } std::println("In total, there are {} beacons.", pointsAt0.size()); - //for (auto const& point : pointsAt0) std::println("{}", point); } int part_two_ans = 0; @@ -408,4 +404,3 @@ int main() { } std::println("In total, they are {} units apart.", part_two_ans); } -}