aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2025/src/day08.cpp83
1 files changed, 46 insertions, 37 deletions
diff --git a/2025/src/day08.cpp b/2025/src/day08.cpp
index 7a3c3b1..6fa3cd6 100644
--- a/2025/src/day08.cpp
+++ b/2025/src/day08.cpp
@@ -2,7 +2,6 @@
2#include <filesystem> 2#include <filesystem>
3#include <fstream> 3#include <fstream>
4#include <iostream> 4#include <iostream>
5#include <map>
6#include <tuple> 5#include <tuple>
7#include <vector> 6#include <vector>
8 7
@@ -14,6 +13,7 @@ class UnionFind {
14public: 13public:
15 explicit UnionFind(size_t size) 14 explicit UnionFind(size_t size)
16 : parent_(size) 15 : parent_(size)
16 , size_(size, 1)
17 { 17 {
18 for ( size_t i = 0; i != size; ++i ) { 18 for ( size_t i = 0; i != size; ++i ) {
19 parent_[i] = i; 19 parent_[i] = i;
@@ -33,18 +33,39 @@ public:
33 a = find(a); 33 a = find(a);
34 b = find(b); 34 b = find(b);
35 35
36 if ( a != b ) { 36 if ( a == b ) {
37 parent_[b] = a; 37 return false;
38 return true;
39 } 38 }
40 return false; 39
40 if ( size_[a] < size_[b] ) {
41 swap(a, b);
42 }
43
44 parent_[b] = a;
45 size_[a] += size_[b];
46
47 return true;
48 }
49
50 [[nodiscard]]
51 vector<size_t> get_component_sizes() const
52 {
53 vector<size_t> sizes;
54 for ( size_t i = 0; i != parent_.size(); ++i ) {
55 if ( parent_[i] == i ) {
56 sizes.emplace_back(size_[i]);
57 }
58 }
59 return sizes;
41 } 60 }
42 61
43private: 62private:
44 vector<size_t> parent_; 63 vector<size_t> parent_;
64 vector<size_t> size_;
45}; 65};
46 66
47using Pos = tuple<long, long, long>; 67using Pos = tuple<long, long, long>; // (x, y, z)
68using Dist = tuple<double, size_t, size_t>; // (Distanz, Von, Nach)
48 69
49vector<Pos> 70vector<Pos>
50read_file(const filesystem::path& filename) 71read_file(const filesystem::path& filename)
@@ -74,11 +95,9 @@ get_distance(const Pos& pos1, const Pos& pos2)
74 return hypot(x1 - x2, y1 - y2, z1 - z2); 95 return hypot(x1 - x2, y1 - y2, z1 - z2);
75} 96}
76 97
77void 98vector<Dist>
78part1(const vector<Pos>& list) 99get_distances(const vector<Pos>& list)
79{ 100{
80 using Dist = tuple<double, size_t, size_t>; // (Distanz, Von, Nach)
81
82 // Distanzen paarweise erfassen... 101 // Distanzen paarweise erfassen...
83 vector<Dist> dists; 102 vector<Dist> dists;
84 for ( size_t i = 0; i != list.size(); ++i ) { 103 for ( size_t i = 0; i != list.size(); ++i ) {
@@ -90,28 +109,26 @@ part1(const vector<Pos>& list)
90 // ... und nach Distanz sortieren 109 // ... und nach Distanz sortieren
91 ranges::sort(dists); 110 ranges::sort(dists);
92 111
112 return dists;
113}
114
115void
116part1(const vector<Pos>& list)
117{
118 const auto dists = get_distances(list);
119
93 UnionFind unionFind(list.size()); 120 UnionFind unionFind(list.size());
94 121
95 // die kĂŒrzesten 1000 Elemente verbinden 122 // die nĂ€chsten 1000 Paare verbinden
96 for ( size_t i = 0; i != 1000; ++i ) { 123 for ( size_t i = 0; i != 1000; ++i ) {
97 const auto [dist, a, b] = dists[i]; 124 const auto [dist, a, b] = dists[i];
98 unionFind.unite(a, b); 125 unionFind.unite(a, b);
99 } 126 }
100 127
101 // die LÀngen der Verbindungen zÀhlen 128 auto sizes = unionFind.get_component_sizes();
102 map<size_t, size_t> compSizes;
103 for ( size_t i = 0; i != list.size(); ++i ) {
104 compSizes[unionFind.find(i)]++;
105 }
106
107 // GrĂ¶ĂŸen finden
108 vector<size_t> sizes;
109 for ( const auto& [root, size]: compSizes ) {
110 sizes.emplace_back(size);
111 }
112 129
113 // Sortieren 130 // Sortieren
114 ranges::sort(sizes, greater<>()); 131 nth_element(sizes.begin(), sizes.begin() + 3, sizes.end(), greater<>());
115 132
116 cout << "Part 1: " << sizes[0] * sizes[1] * sizes[2] << '\n'; 133 cout << "Part 1: " << sizes[0] * sizes[1] * sizes[2] << '\n';
117} 134}
@@ -119,25 +136,17 @@ part1(const vector<Pos>& list)
119void 136void
120part2(const vector<Pos>& list) 137part2(const vector<Pos>& list)
121{ 138{
122 using Dist = tuple<double, size_t, size_t>; // (Distanz, Von, Nach) 139 const auto dists = get_distances(list);
123
124 // Distanzen paarweise erfassen...
125 vector<Dist> dists;
126 for ( size_t i = 0; i != list.size(); ++i ) {
127 for ( size_t j = i + 1; j != list.size(); ++j ) {
128 dists.emplace_back(get_distance(list[i], list[j]), i, j);
129 }
130 }
131
132 // ... und nach Distanz sortieren
133 ranges::sort(dists);
134 140
135 UnionFind unionFind(list.size()); 141 UnionFind unionFind(list.size());
136 142
137 size_t count = 1; 143 // Alle Paare verbinden ...
144 size_t unions = 0;
138 for ( auto [dist, a, b]: dists ) { 145 for ( auto [dist, a, b]: dists ) {
139 if ( unionFind.unite(a, b) ) { 146 if ( unionFind.unite(a, b) ) {
140 if ( ++count == list.size() ) { 147 // ... beim Letzten abbrechen
148 ++unions;
149 if ( unions == list.size() - 1 ) {
141 cout << "Part 2: " << get<0>(list[a]) * get<0>(list[b]) << '\n'; 150 cout << "Part 2: " << get<0>(list[a]) * get<0>(list[b]) << '\n';
142 return; 151 return;
143 } 152 }