aboutsummaryrefslogtreecommitdiff
path: root/2024/src/day24.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2024/src/day24.cpp')
-rw-r--r--2024/src/day24.cpp87
1 files changed, 38 insertions, 49 deletions
diff --git a/2024/src/day24.cpp b/2024/src/day24.cpp
index 3f252a1..c2bd505 100644
--- a/2024/src/day24.cpp
+++ b/2024/src/day24.cpp
@@ -114,15 +114,6 @@ part1(const tuple<map<string, unsigned long>, map<string, tuple<string, string,
114 cout << value << endl; 114 cout << value << endl;
115} 115}
116 116
117string
118make_wire(char chr, unsigned long num)
119{
120 static const size_t MAX_LEN = 10;
121 array<char, MAX_LEN> tmp{};
122 snprintf(tmp.data(), tmp.size(), "%c%02lu", chr, num); // NOLINT
123 return tmp.data();
124}
125
126class RippleCarryAdder { 117class RippleCarryAdder {
127public: 118public:
128 explicit RippleCarryAdder(const tuple<map<string, unsigned long>, map<string, tuple<string, string, string>>>& data) 119 explicit RippleCarryAdder(const tuple<map<string, unsigned long>, map<string, tuple<string, string, string>>>& data)
@@ -131,12 +122,6 @@ public:
131 { 122 {
132 } 123 }
133 124
134 RippleCarryAdder(const map<string, tuple<string, string, string>>& deps, unsigned long x_value, unsigned long y_value)
135 : deps_(deps)
136 {
137 build_inputs(x_value, y_value);
138 }
139
140 void swap_wire(const string& lhs, const string& rhs) 125 void swap_wire(const string& lhs, const string& rhs)
141 { 126 {
142 swap(deps_.at(lhs), deps_.at(rhs)); 127 swap(deps_.at(lhs), deps_.at(rhs));
@@ -197,6 +182,14 @@ public:
197 } 182 }
198 183
199private: 184private:
185 static string make_wire(char chr, unsigned long num)
186 {
187 static const size_t MAX_LEN = 10;
188 array<char, MAX_LEN> tmp{};
189 snprintf(tmp.data(), tmp.size(), "%c%02lu", chr, num); // NOLINT
190 return tmp.data();
191 }
192
200 void build_inputs(unsigned long x_value, unsigned long y_value) 193 void build_inputs(unsigned long x_value, unsigned long y_value)
201 { 194 {
202 inputs_.clear(); 195 inputs_.clear();
@@ -269,54 +262,50 @@ part2(const tuple<map<string, unsigned long>, map<string, tuple<string, string,
269 set<string> solution; 262 set<string> solution;
270 263
271 for ( auto bit = 0UL; bit != MAX_BITS; ++bit ) { 264 for ( auto bit = 0UL; bit != MAX_BITS; ++bit ) {
272 const auto x_value = 1UL << bit; // (1UL << (bit+1)) - 1; 265 const auto x_value = 1UL << bit;
273 const auto y_value = 0UL << bit; 266 const auto y_value = 0UL;
274 267
275 if ( !rca.eval_z(x_value, y_value) ) { 268 if ( !rca.eval_z(x_value, y_value) ) {
276 return; 269 return;
277 } 270 }
278 271
279 const auto failed_bits = rca.test(x_value, y_value); 272 const auto failed_bits = rca.test(x_value, y_value);
280 if ( !failed_bits.empty() ) { 273 if ( failed_bits.empty() ) {
281 set<string> candidates; 274 continue;
282 for ( const auto& wire: failed_bits ) { 275 }
283 rca.collect(wire, candidates);
284 }
285 276
286 const vector<string> foo{ candidates.begin(), candidates.end() }; 277 set<string> unique_candidates;
278 for ( const auto& wire: failed_bits ) {
279 rca.collect(wire, unique_candidates);
280 }
287 281
288 for ( auto i = foo.begin(); i != foo.end(); ++i ) { 282 const vector<string> candidates{ unique_candidates.begin(), unique_candidates.end() };
289 for ( auto j = i + 1; j != foo.end(); ++j ) {
290 auto do_test = [&](unsigned long lhs, unsigned long rhs) -> bool {
291 RippleCarryAdder rca_tester{ data };
292 283
293 rca_tester.swap_wire(*i, *j); 284 for ( auto i = candidates.begin(); i != candidates.end(); ++i ) {
285 for ( auto j = i + 1; j != candidates.end(); ++j ) {
286 auto do_test = [&](const tuple<unsigned long, unsigned long>& test_value) -> bool {
287 const auto [lhs, rhs] = test_value;
294 288
295 if ( !rca_tester.eval_z(lhs, rhs) ) { 289 RippleCarryAdder rca_tester{ data };
296 return false;
297 }
298 return rca_tester.test(lhs, rhs).empty();
299 };
300 290
301 if ( do_test(x_value, y_value) ) { 291 rca_tester.swap_wire(*i, *j);
302 const auto x_value2 = 7UL << (bit - 1);
303 const auto y_value2 = 3UL << (bit - 1);
304 292
305 if ( do_test(x_value2, y_value2) ) { 293 if ( !rca_tester.eval_z(lhs, rhs) ) {
306 const auto x_value3 = 1UL << bit; 294 return false;
307 const auto y_value3 = 1UL << bit; 295 }
296 return rca_tester.test(lhs, rhs).empty();
297 };
308 298
309 if ( do_test(x_value3, y_value3) ) { 299 const vector<tuple<unsigned long, unsigned long>> test_values = {
310 const auto x_value4 = 5UL << (bit - 1); 300 { x_value, y_value },
311 const auto y_value4 = 3UL << (bit - 1); 301 { 7UL << (bit - 1), 3UL << (bit - 1) },
302 { 1UL << bit, 1UL << bit },
303 { 5UL << (bit - 1), 3UL << (bit - 1) }
304 };
312 305
313 if ( do_test(x_value4, y_value4) ) { 306 if ( ranges::all_of(test_values, do_test) ) {
314 solution.insert(*i); 307 solution.insert(*i);
315 solution.insert(*j); 308 solution.insert(*j);
316 }
317 }
318 }
319 }
320 } 309 }
321 } 310 }
322 } 311 }