diff options
| author | Thomas Schmucker <ts@its1.de> | 2023-12-28 11:08:43 +0100 |
|---|---|---|
| committer | Thomas Schmucker <ts@its1.de> | 2023-12-28 11:08:43 +0100 |
| commit | 7b0563c7af27973b97944f4fd7ec92a74d32c9fc (patch) | |
| tree | 13226381d81379279dd901d3b1059f0e6bdede4d | |
| parent | 4317917a8500f29a5af588d25912404c300fcedb (diff) | |
| download | advent-of-code-7b0563c7af27973b97944f4fd7ec92a74d32c9fc.tar.gz advent-of-code-7b0563c7af27973b97944f4fd7ec92a74d32c9fc.tar.bz2 advent-of-code-7b0563c7af27973b97944f4fd7ec92a74d32c9fc.zip | |
Lösungen für Tag 23, Teil 2
| -rw-r--r-- | src/day23.cpp | 95 |
1 files changed, 80 insertions, 15 deletions
diff --git a/src/day23.cpp b/src/day23.cpp index 6e60e55..207a62c 100644 --- a/src/day23.cpp +++ b/src/day23.cpp | |||
| @@ -1,14 +1,18 @@ | |||
| 1 | #include <algorithm> | 1 | #include <algorithm> |
| 2 | #include <array> | 2 | #include <array> |
| 3 | #include <fstream> | 3 | #include <fstream> |
| 4 | #include <functional> | ||
| 4 | #include <iostream> | 5 | #include <iostream> |
| 5 | #include <iterator> | 6 | #include <iterator> |
| 7 | #include <map> | ||
| 6 | #include <queue> | 8 | #include <queue> |
| 7 | #include <set> | 9 | #include <set> |
| 8 | #include <string> | 10 | #include <string> |
| 9 | #include <vector> | 11 | #include <vector> |
| 10 | using namespace std; | 12 | using namespace std; |
| 11 | 13 | ||
| 14 | using position_t = tuple<size_t, size_t>; | ||
| 15 | |||
| 12 | vector<string> | 16 | vector<string> |
| 13 | read_file(string_view filename) | 17 | read_file(string_view filename) |
| 14 | { | 18 | { |
| @@ -22,10 +26,10 @@ read_file(string_view filename) | |||
| 22 | return data; | 26 | return data; |
| 23 | } | 27 | } |
| 24 | 28 | ||
| 25 | set<tuple<size_t, size_t>> | 29 | set<position_t> |
| 26 | get_neighbours(const vector<string>& maze, tuple<size_t, size_t> possition) | 30 | get_neighbours(const vector<string>& maze, position_t possition) |
| 27 | { | 31 | { |
| 28 | static const tuple<size_t, size_t> deltas[] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // NOLINT | 32 | static const position_t deltas[] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // NOLINT |
| 29 | 33 | ||
| 30 | static const auto SYM_UP = '^'; | 34 | static const auto SYM_UP = '^'; |
| 31 | static const auto SYM_RIGHT = '>'; | 35 | static const auto SYM_RIGHT = '>'; |
| @@ -45,7 +49,7 @@ get_neighbours(const vector<string>& maze, tuple<size_t, size_t> possition) | |||
| 45 | return { make_tuple(row, col - 1) }; | 49 | return { make_tuple(row, col - 1) }; |
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | set<tuple<size_t, size_t>> positions; | 52 | set<position_t> positions; |
| 49 | 53 | ||
| 50 | for ( const auto& delta: deltas ) { | 54 | for ( const auto& delta: deltas ) { |
| 51 | const auto new_row = row + get<0>(delta); | 55 | const auto new_row = row + get<0>(delta); |
| @@ -78,27 +82,54 @@ get_neighbours(const vector<string>& maze, tuple<size_t, size_t> possition) | |||
| 78 | return positions; | 82 | return positions; |
| 79 | } | 83 | } |
| 80 | 84 | ||
| 85 | set<position_t> | ||
| 86 | get_neighbours2(const vector<string>& maze, position_t possition) | ||
| 87 | { | ||
| 88 | static const position_t deltas[] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // NOLINT | ||
| 89 | |||
| 90 | const auto [row, col] = possition; | ||
| 91 | |||
| 92 | set<position_t> positions; | ||
| 93 | |||
| 94 | for ( const auto& delta: deltas ) { | ||
| 95 | const auto new_row = row + get<0>(delta); | ||
| 96 | const auto new_col = col + get<1>(delta); | ||
| 97 | |||
| 98 | if ( new_row >= maze.size() || new_col >= maze[0].size() ) { | ||
| 99 | continue; | ||
| 100 | } | ||
| 101 | |||
| 102 | if ( maze[new_row][new_col] == '#' ) { | ||
| 103 | continue; | ||
| 104 | } | ||
| 105 | |||
| 106 | positions.emplace(new_row, new_col); | ||
| 107 | } | ||
| 108 | |||
| 109 | return positions; | ||
| 110 | } | ||
| 111 | |||
| 81 | void | 112 | void |
| 82 | part1(const vector<string>& maze) | 113 | part1(const vector<string>& maze) |
| 83 | { | 114 | { |
| 84 | const tuple<size_t, size_t> start = { 0, maze[0].find('.') }; | 115 | const position_t start = { 0, maze[0].find('.') }; |
| 85 | const tuple<size_t, size_t> end = { maze.size() - 1, maze[maze.size() - 1].find('.') }; | 116 | const position_t end = { maze.size() - 1, maze[maze.size() - 1].find('.') }; |
| 86 | 117 | ||
| 87 | queue<tuple<tuple<size_t, size_t>, set<tuple<size_t, size_t>>>> queue; | 118 | queue<tuple<position_t, set<position_t>>> queue; |
| 88 | 119 | ||
| 89 | queue.emplace(start, set<tuple<size_t, size_t>>{}); | 120 | queue.emplace(start, set<position_t>{}); |
| 90 | 121 | ||
| 91 | size_t longest = 0; | 122 | size_t longest = 0; |
| 92 | while ( !queue.empty() ) { | 123 | while ( !queue.empty() ) { |
| 93 | auto [position, seen] = queue.front(); | 124 | auto [current_position, seen] = queue.front(); |
| 94 | queue.pop(); | 125 | queue.pop(); |
| 95 | 126 | ||
| 96 | while ( position != end ) { | 127 | while ( current_position != end ) { |
| 97 | seen.emplace(position); | 128 | seen.emplace(current_position); |
| 98 | 129 | ||
| 99 | const auto neighbours = get_neighbours(maze, position); | 130 | const auto neighbours = get_neighbours(maze, current_position); |
| 100 | 131 | ||
| 101 | vector<tuple<size_t, size_t>> next_positions; | 132 | vector<position_t> next_positions; |
| 102 | 133 | ||
| 103 | // { neighbours \ seen } | 134 | // { neighbours \ seen } |
| 104 | set_difference(neighbours.begin(), neighbours.end(), | 135 | set_difference(neighbours.begin(), neighbours.end(), |
| @@ -109,22 +140,56 @@ part1(const vector<string>& maze) | |||
| 109 | break; | 140 | break; |
| 110 | } | 141 | } |
| 111 | 142 | ||
| 112 | position = next_positions[0]; | 143 | current_position = next_positions[0]; |
| 113 | 144 | ||
| 114 | for ( size_t idx = 1; idx != next_positions.size(); ++idx ) { | 145 | for ( size_t idx = 1; idx != next_positions.size(); ++idx ) { |
| 115 | queue.emplace(next_positions[idx], seen); | 146 | queue.emplace(next_positions[idx], seen); |
| 116 | } | 147 | } |
| 117 | } | 148 | } |
| 118 | if ( position == end ) { | 149 | if ( current_position == end ) { |
| 119 | longest = max(longest, seen.size()); | 150 | longest = max(longest, seen.size()); |
| 120 | } | 151 | } |
| 121 | } | 152 | } |
| 122 | cout << longest << endl; | 153 | cout << longest << endl; |
| 123 | } | 154 | } |
| 124 | 155 | ||
| 156 | void | ||
| 157 | part2(const vector<string>& maze) | ||
| 158 | { | ||
| 159 | const position_t start = { 0, maze[0].find('.') }; | ||
| 160 | const position_t end = { maze.size() - 1, maze[maze.size() - 1].find('.') }; | ||
| 161 | |||
| 162 | vector<vector<bool>> visited(maze.size(), vector<bool>(maze[0].size())); | ||
| 163 | |||
| 164 | function<long(position_t, long)> findmax = [&](position_t position, long current) -> long { | ||
| 165 | const auto [row, col] = position; | ||
| 166 | |||
| 167 | if ( visited[row][col] ) { | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | if ( position == end ) { | ||
| 172 | return current; | ||
| 173 | } | ||
| 174 | |||
| 175 | long value = 0; | ||
| 176 | visited[row][col] = true; | ||
| 177 | for ( const auto& neighbour: get_neighbours2(maze, position) ) { | ||
| 178 | value = max(value, findmax(neighbour, current + 1)); | ||
| 179 | } | ||
| 180 | visited[row][col] = false; | ||
| 181 | |||
| 182 | return value; | ||
| 183 | }; | ||
| 184 | |||
| 185 | auto value = findmax(start, 0); | ||
| 186 | cout << value << endl; | ||
| 187 | } | ||
| 188 | |||
| 125 | int | 189 | int |
| 126 | main() | 190 | main() |
| 127 | { | 191 | { |
| 128 | const auto maze = read_file("data/day23.txt"); | 192 | const auto maze = read_file("data/day23.txt"); |
| 129 | part1(maze); | 193 | part1(maze); |
| 194 | part2(maze); | ||
| 130 | } | 195 | } |
