+1
data/02/input.txt
+1
data/02/input.txt
···
1
+
503950-597501,73731-100184,79705998-79873916,2927-3723,35155-50130,52-82,1139-1671,4338572-4506716,1991-2782,1314489-1387708,8810810-8984381,762581-829383,214957-358445,9947038-10058264,4848455367-4848568745,615004-637022,5827946-5911222,840544-1026063,19-46,372804-419902,486-681,815-1117,3928-5400,28219352-28336512,6200009-6404247,174-261,151131150-151188124,19323-26217,429923-458519,5151467682-5151580012,9354640427-9354772901,262-475,100251-151187,5407-9794,8484808500-8484902312,86-129,2-18
+1
data/02/test.txt
+1
data/02/test.txt
···
1
+
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124
+98
src/02/solution.cxx
+98
src/02/solution.cxx
···
1
+
#include "common/getinputpath.h"
2
+
#include <algorithm>
3
+
#include <filesystem>
4
+
#include <format>
5
+
#include <fstream>
6
+
#include <functional>
7
+
#include <print>
8
+
#include <ranges>
9
+
#include <regex>
10
+
#include <string>
11
+
12
+
#ifndef DATA_FOLDER
13
+
#error \
14
+
"Meson must have defined the DATA_FOLDER somewhere in build scripts. Go check it."
15
+
#endif // !DATA_FOLDER
16
+
17
+
const std::filesystem::path input_path = get_input_path(DATA_FOLDER);
18
+
constexpr const char delimiter = ',';
19
+
20
+
struct NumberProfile {
21
+
long number;
22
+
bool part1_valid;
23
+
bool part2_valid;
24
+
};
25
+
26
+
NumberProfile is_valid(long id) {
27
+
std::string id_string = std::to_string(id);
28
+
29
+
bool part1_valid = true;
30
+
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
+
}
47
+
}
48
+
49
+
return NumberProfile{
50
+
.number = id,
51
+
.part1_valid = part1_valid,
52
+
.part2_valid = part2_valid,
53
+
};
54
+
}
55
+
56
+
// Ryzen 5 5600G runtime: 25m51s
57
+
int main() {
58
+
std::ifstream input(input_path);
59
+
if (!input.is_open()) {
60
+
std::println("Something wrong happened. Can't open file {}",
61
+
input_path.string());
62
+
return 1;
63
+
}
64
+
65
+
unsigned long long password_part_1 = 0;
66
+
unsigned long long password_part_2 = 0;
67
+
68
+
// loop hell incoming
69
+
for (std::string t = ""; std::getline(input, t, delimiter);) {
70
+
std::println("Checking range {}", t);
71
+
auto left = t.substr(0, t.find('-'));
72
+
auto right = t.substr(t.find('-') + 1);
73
+
74
+
auto ids = std::ranges::views::iota(std::stol(left), std::stol(right) + 1) |
75
+
std::ranges::views::transform(is_valid);
76
+
auto invalid_ids_part1 =
77
+
ids | std::ranges::views::filter([](NumberProfile i) {
78
+
return !i.part1_valid;
79
+
}) |
80
+
std::ranges::views::transform([](NumberProfile i) { return i.number; });
81
+
82
+
auto invalid_ids_part2 =
83
+
ids | std::ranges::views::filter([](NumberProfile i) {
84
+
return !i.part2_valid;
85
+
}) |
86
+
std::ranges::views::transform([](NumberProfile i) { return i.number; });
87
+
88
+
auto sum_part1 = std::ranges::fold_left(invalid_ids_part1, 0, std::plus{});
89
+
password_part_1 += sum_part1;
90
+
91
+
auto sum_part2 = std::ranges::fold_left(invalid_ids_part2, 0, std::plus{});
92
+
password_part_2 += sum_part2;
93
+
}
94
+
95
+
std::println("Eureka! {} / {}", password_part_1, password_part_2);
96
+
97
+
return 0;
98
+
}
+9
src/common/getinputpath.cxx
+9
src/common/getinputpath.cxx
+3
src/common/getinputpath.h
+3
src/common/getinputpath.h