+11
-23
src/07/solution.cxx
+11
-23
src/07/solution.cxx
···
63
63
size_t x = 0;
64
64
size_t y = 0;
65
65
66
-
bool operator==(Position other) {
67
-
return this->x == other.x && this->y == other.y;
66
+
bool operator==(const Position& other) const {
67
+
return x == other.x && y == other.y;
68
68
}
69
69
70
-
bool operator<(Position other) {
71
-
return this->x < other.x && this->y < other.y;
72
-
}
73
-
74
-
// std::map is a *sorted* structure, so it requires its types to implement
75
-
// comparators or not use std::map with unsortable values at all. I did not
76
-
// want to implement a comparator at the moment. this is part of a workaround.
77
-
std::string encode() { return std::format("{}/{}", this->x, this->y); }
78
-
79
-
static Position decode(std::string position) {
80
-
auto slash_idx = position.find_first_of('/');
81
-
auto x = std::stoll(position.substr(0, slash_idx));
82
-
auto y = std::stoll(position.substr(slash_idx + 1));
83
-
return Position{.x = static_cast<size_t>(x), .y = static_cast<size_t>(y)};
70
+
bool operator<(const Position& other) const {
71
+
return y < other.y || (y == other.y && x < other.x);
84
72
}
85
73
};
86
74
87
75
long long count_possible_paths(std::vector<std::string> &data,
88
76
Position position,
89
-
std::map<std::string, long long> &cache) {
77
+
std::map<Position, long long> &cache) {
90
78
// TODO
91
79
if (position.y == data.size()) { // if we reached bottom
92
80
return 1;
···
103
91
Position right = Position{.x = position.x + 1, .y = position.y};
104
92
105
93
// a weird workaround to satisfy some static checks. maps must be sortable.
106
-
if (cache.contains(position.encode())) {
107
-
result = cache[position.encode()];
94
+
if (cache.contains(position)) {
95
+
result = cache[position];
108
96
} else {
109
97
result = count_possible_paths(data, left, cache) +
110
98
count_possible_paths(data, right, cache);
111
99
112
-
cache[position.encode()] = result;
100
+
cache[position] = result;
113
101
}
114
102
}
115
103
···
117
105
}
118
106
119
107
long long count_possible_paths(std::vector<std::string> &data,
120
-
std::map<std::string, long long> &cache) {
108
+
std::map<Position, long long> &cache) {
121
109
Position start{
122
110
.x = data[0].find_first_of('S'),
123
111
.y = 0,
···
125
113
return count_possible_paths(data, start, cache);
126
114
}
127
115
128
-
// runtime on Ryzen 5 5600G: 0.004s
116
+
// runtime on Ryzen 5 5600G: 0.003s
129
117
int main() {
130
118
auto data_path = get_input_path(DATA_FOLDER);
131
119
std::ifstream data_ifstream(data_path);
···
143
131
144
132
long long password_part_1 = count_beams_split(data);
145
133
146
-
std::map<std::string, long long> cache{};
134
+
std::map<Position, long long> cache{};
147
135
long long password_part_2 = count_possible_paths(data, cache); // this one too
148
136
149
137
std::println("Eureka! {} / {}", password_part_1, password_part_2);