Advent of Code 2025, done in C++

day[02]: optimized the solutions

bpavuk.neocities.org 72bcb35f 2eb1d0b7

verified
Changed files
+30 -22
src
+30 -22
src/02/solution.cxx
··· 4 4 #include <format> 5 5 #include <fstream> 6 6 #include <functional> 7 + #include <iterator> 7 8 #include <print> 8 9 #include <ranges> 9 10 #include <regex> 10 11 #include <string> 12 + #include <vector> 11 13 12 14 #ifndef DATA_FOLDER 13 15 #error \ ··· 23 25 bool part2_valid; 24 26 }; 25 27 26 - NumberProfile is_valid(long id) { 28 + [[nodiscard]] NumberProfile is_valid(long id) { 27 29 std::string id_string = std::to_string(id); 28 30 29 31 bool part1_valid = true; 30 32 bool part2_valid = true; 31 - 32 - for (unsigned long i = 1; i <= id_string.length(); ++i) { 33 - auto substring = id_string.substr(0, i); 34 - auto regex_str_part_1 = std::format("({}){{2}}", substring); 35 - auto regex_str_part_2 = std::format("({}){{2,}}", substring); 36 - auto regex_part_1 = std::regex(regex_str_part_1); 37 - auto regex_part_2 = std::regex(regex_str_part_2); 38 - if (part1_valid) { 39 - part1_valid = !std::regex_match(id_string, regex_part_1); 40 - } 41 - if (part2_valid) { 42 - part2_valid = !std::regex_match(id_string, regex_part_2); 43 - } 44 - if (!part1_valid && !part2_valid) { 45 - break; 46 - } 33 + 34 + // repeats 2 times 35 + if (id_string.length() % 2 == 0 && part1_valid) { 36 + bool invalid = id_string.substr(0, id_string.length() / 2) == 37 + id_string.substr(id_string.length() / 2); 38 + part1_valid = !invalid; 39 + } 40 + 41 + // repeats more than 2 times 42 + if (id_string.length() >= 2 && part2_valid) { 43 + auto t = id_string + id_string; 44 + part2_valid = 45 + t.substr(1, t.length() - 2).find(id_string) == std::string::npos; 47 46 } 48 47 49 48 return NumberProfile{ ··· 53 52 }; 54 53 } 55 54 56 - // Ryzen 5 5600G runtime: 25m51s 55 + // Ryzen 5 5600G runtime: 1s494ms 57 56 int main() { 58 57 std::ifstream input(input_path); 59 58 if (!input.is_open()) { ··· 71 70 auto left = t.substr(0, t.find('-')); 72 71 auto right = t.substr(t.find('-') + 1); 73 72 74 - auto ids = std::ranges::views::iota(std::stol(left), std::stol(right) + 1) | 75 - std::ranges::views::transform(is_valid); 73 + auto ids = std::vector<NumberProfile>(std::stol(right) - std::stol(left)); 74 + 75 + { 76 + auto ids_num = std::vector<long>(std::stol(right) - std::stol(left)); 77 + std::ranges::iota(ids_num.begin(), ids_num.end(), std::stol(left)); 78 + std::ranges::transform(ids_num, std::back_inserter(ids), 79 + [](auto i) { return is_valid(i); }); 80 + } 81 + 76 82 auto invalid_ids_part1 = 77 83 ids | std::ranges::views::filter([](NumberProfile i) { 78 84 return !i.part1_valid; ··· 85 91 }) | 86 92 std::ranges::views::transform([](NumberProfile i) { return i.number; }); 87 93 88 - auto sum_part1 = std::ranges::fold_left(invalid_ids_part1, 0, std::plus{}); 94 + auto sum_part1 = 95 + std::ranges::fold_left(invalid_ids_part1, 0ULL, std::plus<>{}); 89 96 password_part_1 += sum_part1; 90 97 91 - auto sum_part2 = std::ranges::fold_left(invalid_ids_part2, 0, std::plus{}); 98 + auto sum_part2 = 99 + std::ranges::fold_left(invalid_ids_part2, 0ULL, std::plus<>{}); 92 100 password_part_2 += sum_part2; 93 101 } 94 102