+5
.clang-format
+5
.clang-format
+98
-96
src/07/solution.cxx
+98
-96
src/07/solution.cxx
···
1
-
#include "common/getinputpath.h"
2
1
#include <cstddef>
3
2
#include <format>
4
3
#include <fstream>
···
7
6
#include <string>
8
7
#include <vector>
9
8
10
-
void render(std::vector<std::string> &data) {
11
-
if (data.size() < 2) {
12
-
return;
13
-
}
9
+
#include "common/getinputpath.h"
10
+
11
+
void render(std::vector<std::string>& data) {
12
+
if (data.size() < 2) {
13
+
return;
14
+
}
14
15
15
-
for (size_t i = 1; i < data.size(); ++i) {
16
-
auto &previous = data[i - 1];
17
-
auto ¤t = data[i];
16
+
for (size_t i = 1; i < data.size(); ++i) {
17
+
auto& previous = data[i - 1];
18
+
auto& current = data[i];
18
19
19
-
for (size_t ch = 0; ch < current.size(); ++ch) {
20
-
char previous_ch = previous[ch];
21
-
char current_ch = current[ch];
22
-
if (previous_ch != 'S' && previous_ch != '|') {
23
-
continue;
24
-
}
20
+
for (size_t ch = 0; ch < current.size(); ++ch) {
21
+
char previous_ch = previous[ch];
22
+
char current_ch = current[ch];
23
+
if (previous_ch != 'S' && previous_ch != '|') {
24
+
continue;
25
+
}
25
26
26
-
// render
27
-
if (current_ch == '^') {
28
-
// split
29
-
if (ch > 0) {
30
-
current[ch - 1] = '|';
31
-
}
32
-
if (ch < current.size()) {
33
-
current[ch + 1] = '|';
27
+
// render
28
+
if (current_ch == '^') {
29
+
// split
30
+
if (ch > 0) {
31
+
current[ch - 1] = '|';
32
+
}
33
+
if (ch < current.size()) {
34
+
current[ch + 1] = '|';
35
+
}
36
+
} else {
37
+
current[ch] = '|';
38
+
}
34
39
}
35
-
} else {
36
-
current[ch] = '|';
37
-
}
38
40
}
39
-
}
40
41
}
41
42
42
-
long long count_beams_split(std::vector<std::string> &data) {
43
-
if (data.size() < 2) {
44
-
return 0;
45
-
}
46
-
auto out = 0;
43
+
long long count_beams_split(std::vector<std::string>& data) {
44
+
if (data.size() < 2) {
45
+
return 0;
46
+
}
47
+
auto out = 0;
47
48
48
-
for (size_t i = 1; i < data.size(); ++i) {
49
-
auto &previous = data[i - 1];
50
-
auto ¤t = data[i];
49
+
for (size_t i = 1; i < data.size(); ++i) {
50
+
auto& previous = data[i - 1];
51
+
auto& current = data[i];
51
52
52
-
for (size_t ch = 0; ch < current.size(); ++ch) {
53
-
if (previous[ch] == '|' && current[ch] == '^') {
54
-
out += 1;
55
-
}
53
+
for (size_t ch = 0; ch < current.size(); ++ch) {
54
+
if (previous[ch] == '|' && current[ch] == '^') {
55
+
out += 1;
56
+
}
57
+
}
56
58
}
57
-
}
58
59
59
-
return out;
60
+
return out;
60
61
}
61
62
62
63
struct Position {
63
-
size_t x = 0;
64
-
size_t y = 0;
64
+
size_t x = 0;
65
+
size_t y = 0;
65
66
66
-
bool operator==(const Position& other) const {
67
-
return x == other.x && y == other.y;
68
-
}
67
+
bool operator==(const Position& other) const {
68
+
return x == other.x && y == other.y;
69
+
}
69
70
70
-
bool operator<(const Position& other) const {
71
-
return y < other.y || (y == other.y && x < other.x);
72
-
}
71
+
bool operator<(const Position& other) const {
72
+
return y < other.y || (y == other.y && x < other.x);
73
+
}
73
74
};
74
75
75
-
long long count_possible_paths(std::vector<std::string> &data,
76
-
Position position,
77
-
std::map<Position, long long> &cache) {
78
-
// TODO
79
-
if (position.y == data.size()) { // if we reached bottom
80
-
return 1;
81
-
}
82
-
long long result = 0;
83
-
if (data[position.y][position.x] == '|' ||
84
-
data[position.y][position.x] == 'S') {
76
+
long long count_possible_paths(std::vector<std::string>& data,
77
+
Position position,
78
+
std::map<Position, long long>& cache) {
79
+
// TODO
80
+
if (position.y == data.size()) { // if we reached bottom
81
+
return 1;
82
+
}
83
+
long long result = 0;
84
+
if (data[position.y][position.x] == '|' ||
85
+
data[position.y][position.x] == 'S') {
86
+
Position new_pos{.x = position.x, .y = position.y + 1};
87
+
result = count_possible_paths(data, new_pos, cache);
85
88
86
-
Position new_pos{.x = position.x, .y = position.y + 1};
87
-
result = count_possible_paths(data, new_pos, cache);
89
+
} else if (data[position.y][position.x] == '^') {
90
+
Position left = Position{.x = position.x - 1, .y = position.y};
91
+
Position right = Position{.x = position.x + 1, .y = position.y};
88
92
89
-
} else if (data[position.y][position.x] == '^') {
90
-
Position left = Position{.x = position.x - 1, .y = position.y};
91
-
Position right = Position{.x = position.x + 1, .y = position.y};
92
-
93
-
// a weird workaround to satisfy some static checks. maps must be sortable.
94
-
if (cache.contains(position)) {
95
-
result = cache[position];
96
-
} else {
97
-
result = count_possible_paths(data, left, cache) +
98
-
count_possible_paths(data, right, cache);
93
+
// a weird workaround to satisfy some static checks. maps must
94
+
// be sortable.
95
+
if (cache.contains(position)) {
96
+
result = cache[position];
97
+
} else {
98
+
result = count_possible_paths(data, left, cache) +
99
+
count_possible_paths(data, right, cache);
99
100
100
-
cache[position] = result;
101
+
cache[position] = result;
102
+
}
101
103
}
102
-
}
103
104
104
-
return result;
105
+
return result;
105
106
}
106
107
107
-
long long count_possible_paths(std::vector<std::string> &data,
108
-
std::map<Position, long long> &cache) {
109
-
Position start{
110
-
.x = data[0].find_first_of('S'),
111
-
.y = 0,
112
-
};
113
-
return count_possible_paths(data, start, cache);
108
+
long long count_possible_paths(std::vector<std::string>& data,
109
+
std::map<Position, long long>& cache) {
110
+
Position start{
111
+
.x = data[0].find_first_of('S'),
112
+
.y = 0,
113
+
};
114
+
return count_possible_paths(data, start, cache);
114
115
}
115
116
116
117
// runtime on Ryzen 5 5600G: 0.003s
117
118
int main() {
118
-
auto data_path = get_input_path(DATA_FOLDER);
119
-
std::ifstream data_ifstream(data_path);
120
-
if (!data_ifstream.is_open()) {
121
-
std::println("Cannot open the file at {}", data_path.string());
122
-
return 1;
123
-
}
119
+
auto data_path = get_input_path(DATA_FOLDER);
120
+
std::ifstream data_ifstream(data_path);
121
+
if (!data_ifstream.is_open()) {
122
+
std::println("Cannot open the file at {}", data_path.string());
123
+
return 1;
124
+
}
124
125
125
-
std::vector<std::string> data{};
126
-
for (std::string t; std::getline(data_ifstream, t);) {
127
-
data.push_back(t);
128
-
}
126
+
std::vector<std::string> data{};
127
+
for (std::string t; std::getline(data_ifstream, t);) {
128
+
data.push_back(t);
129
+
}
129
130
130
-
render(data); // this has some great potential for TUI visualization
131
+
render(data); // this has some great potential for TUI visualization
131
132
132
-
long long password_part_1 = count_beams_split(data);
133
+
long long password_part_1 = count_beams_split(data);
133
134
134
-
std::map<Position, long long> cache{};
135
-
long long password_part_2 = count_possible_paths(data, cache); // this one too
135
+
std::map<Position, long long> cache{};
136
+
long long password_part_2 =
137
+
count_possible_paths(data, cache); // this one too
136
138
137
-
std::println("Eureka! {} / {}", password_part_1, password_part_2);
139
+
std::println("Eureka! {} / {}", password_part_1, password_part_2);
138
140
139
-
return 0;
141
+
return 0;
140
142
}