Advent of Code 2025, done in C++

day[07]: further simplified the code; fixed comparators

bpavuk.neocities.org 8d9f1ef3 a38a0281

verified
Changed files
+11 -23
src
+11 -23
src/07/solution.cxx
··· 63 size_t x = 0; 64 size_t y = 0; 65 66 - bool operator==(Position other) { 67 - return this->x == other.x && this->y == other.y; 68 } 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)}; 84 } 85 }; 86 87 long long count_possible_paths(std::vector<std::string> &data, 88 Position position, 89 - std::map<std::string, long long> &cache) { 90 // TODO 91 if (position.y == data.size()) { // if we reached bottom 92 return 1; ··· 103 Position right = Position{.x = position.x + 1, .y = position.y}; 104 105 // a weird workaround to satisfy some static checks. maps must be sortable. 106 - if (cache.contains(position.encode())) { 107 - result = cache[position.encode()]; 108 } else { 109 result = count_possible_paths(data, left, cache) + 110 count_possible_paths(data, right, cache); 111 112 - cache[position.encode()] = result; 113 } 114 } 115 ··· 117 } 118 119 long long count_possible_paths(std::vector<std::string> &data, 120 - std::map<std::string, long long> &cache) { 121 Position start{ 122 .x = data[0].find_first_of('S'), 123 .y = 0, ··· 125 return count_possible_paths(data, start, cache); 126 } 127 128 - // runtime on Ryzen 5 5600G: 0.004s 129 int main() { 130 auto data_path = get_input_path(DATA_FOLDER); 131 std::ifstream data_ifstream(data_path); ··· 143 144 long long password_part_1 = count_beams_split(data); 145 146 - std::map<std::string, long long> cache{}; 147 long long password_part_2 = count_possible_paths(data, cache); // this one too 148 149 std::println("Eureka! {} / {}", password_part_1, password_part_2);
··· 63 size_t x = 0; 64 size_t y = 0; 65 66 + bool operator==(const Position& other) const { 67 + return x == other.x && y == other.y; 68 } 69 70 + bool operator<(const Position& other) const { 71 + return y < other.y || (y == other.y && x < other.x); 72 } 73 }; 74 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; ··· 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); 99 100 + cache[position] = result; 101 } 102 } 103 ··· 105 } 106 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, ··· 113 return count_possible_paths(data, start, cache); 114 } 115 116 + // runtime on Ryzen 5 5600G: 0.003s 117 int main() { 118 auto data_path = get_input_path(DATA_FOLDER); 119 std::ifstream data_ifstream(data_path); ··· 131 132 long long password_part_1 = count_beams_split(data); 133 134 + std::map<Position, long long> cache{}; 135 long long password_part_2 = count_possible_paths(data, cache); // this one too 136 137 std::println("Eureka! {} / {}", password_part_1, password_part_2);