Advent of Code 2025, done in C++

day[01]: optimized the solutions, improved code quality

bpavuk.neocities.org eaa67bde 411f866c

verified
Changed files
+36 -21
src
+36 -21
src/01/solution.cxx
··· 2 2 #include <algorithm> 3 3 #include <cstdlib> 4 4 #include <filesystem> 5 + #include <format> 5 6 #include <fstream> 6 7 #include <print> 7 - #include <ranges> 8 8 #include <string> 9 9 #include <string_view> 10 10 ··· 18 18 int value = 50; 19 19 }; 20 20 21 + struct RotationResult { 22 + int new_value; 23 + int crossed_0; 24 + }; 25 + 21 26 // @return how many times the rotary crossed 0, but *not* the times it stopped 22 27 // at 0 23 - int rotate(Rotary &rotary, int value) { 28 + RotationResult rotate(const Rotary &rotary, const int value) { 24 29 int result = rotary.value + value; 25 - int crossed_0 = 0; 30 + 31 + int begin = std::min(result, rotary.value); 32 + int end = std::max(result, rotary.value); 26 33 27 - int begin = std::min(result, rotary.value); // looks modern, but it's really 28 - int end = std::max(result, rotary.value); // hideous 29 - auto range = std::ranges::views::iota(begin + 1, end) | 30 - std::ranges::views::filter([](int x) { return x % 100 == 0; }); 34 + auto begin_norm = 0; 35 + if (begin % 100 != 0) { 36 + if (begin >= 0) { 37 + begin_norm = begin - (begin % 100); 38 + } else { 39 + begin_norm = (begin - 100) / 100 * 100; 40 + } 41 + } else { 42 + begin_norm = begin; 43 + } 31 44 32 - for (int _ : range) { // Kotlin .forEach would have looked so much better 33 - crossed_0 += 1; 45 + auto end_norm = 0; 46 + if (end % 100 != 0) { 47 + end_norm = end + (100 - end % 100); 48 + } else { 49 + end_norm = end; 34 50 } 35 51 36 - while (result < 0) { 37 - result += 100; 52 + auto crossed_0 = (end_norm - begin_norm) / 100 - 1; 53 + 54 + if (result < 0) { 55 + result += std::abs(result / 100 * 100) + 100; 38 56 } 39 - while (result > 99) { 40 - result -= 100; 57 + if (result > 99) { 58 + result %= 100; 41 59 } 42 - rotary.value = result; 43 60 44 - return crossed_0; 61 + return RotationResult{.new_value = result, .crossed_0 = crossed_0}; 45 62 } 46 63 47 64 int main() { ··· 69 86 // horrendous code below 70 87 71 88 for (std::string line; std::getline(input, line);) { 89 + // parser is okay-ish, I trust AoC inputs 72 90 std::string_view rotation = std::string_view(line.data(), 1); 73 91 std::string_view number_sv = std::string_view(line.data() + 1); 74 92 75 93 auto number = std::stoi(number_sv.data()); 76 - 77 94 if (rotation == "L") { 78 95 number = -number; 79 96 } 80 97 81 - // ridiculous - a function has both side effect and a return value 82 - // this shit reminds me of out parameter convention so much... 83 - times_crossed_0 += rotate(rotary, number); 84 - 98 + auto result = rotate(rotary, number); 99 + times_crossed_0 += result.crossed_0; 100 + rotary.value = result.new_value; 85 101 if (rotary.value == 0) { 86 102 password_part_1 += 1; 87 103 } ··· 91 107 92 108 std::println("Eureka! {} / {}", password_part_1, password_part_2); 93 109 94 - input.close(); 95 110 return 0; 96 111 }