diff options
Diffstat (limited to '2016/src/day22.cpp')
| -rw-r--r-- | 2016/src/day22.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/2016/src/day22.cpp b/2016/src/day22.cpp new file mode 100644 index 0000000..c4d1642 --- /dev/null +++ b/2016/src/day22.cpp | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | #include <filesystem> | ||
| 2 | #include <fstream> | ||
| 3 | #include <iostream> | ||
| 4 | #include <map> | ||
| 5 | #include <regex> | ||
| 6 | #include <set> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | using namespace std; | ||
| 11 | |||
| 12 | namespace { | ||
| 13 | |||
| 14 | struct Node { | ||
| 15 | int x, y; | ||
| 16 | int size, used, avail, percent; | ||
| 17 | |||
| 18 | [[nodiscard]] | ||
| 19 | tuple<int, int> pos() const | ||
| 20 | { | ||
| 21 | return { x, y }; | ||
| 22 | } | ||
| 23 | }; | ||
| 24 | |||
| 25 | vector<Node> | ||
| 26 | readNodes(const filesystem::path& filename) | ||
| 27 | { | ||
| 28 | static const regex line_regex(R"(^/dev/grid/node-x(\d+)-y(\d+)\s+(\d+)T\s+(\d+)T\s+(\d+)T\s+(\d+)%$)"); | ||
| 29 | |||
| 30 | ifstream file{ filename }; | ||
| 31 | vector<Node> nodes; | ||
| 32 | |||
| 33 | for ( string line; getline(file, line); ) { | ||
| 34 | smatch match; | ||
| 35 | |||
| 36 | if ( !regex_match(line, match, line_regex) ) { | ||
| 37 | continue; | ||
| 38 | } | ||
| 39 | |||
| 40 | Node node{ | ||
| 41 | .x = stoi(match[1].str()), // x | ||
| 42 | .y = stoi(match[2].str()), // y | ||
| 43 | .size = stoi(match[3].str()), // size | ||
| 44 | .used = stoi(match[4].str()), // used | ||
| 45 | .avail = stoi(match[5].str()), // avail | ||
| 46 | .percent = stoi(match[6].str()) // percent | ||
| 47 | }; | ||
| 48 | |||
| 49 | nodes.emplace_back(node); | ||
| 50 | } | ||
| 51 | |||
| 52 | return nodes; | ||
| 53 | } | ||
| 54 | |||
| 55 | void | ||
| 56 | part1(const vector<Node>& nodes) | ||
| 57 | { | ||
| 58 | long count = 0; | ||
| 59 | |||
| 60 | for ( size_t i = 0; i != nodes.size(); ++i ) { | ||
| 61 | if ( nodes[i].used == 0 ) { | ||
| 62 | continue; | ||
| 63 | } | ||
| 64 | |||
| 65 | for ( size_t j = 0; j != nodes.size(); ++j ) { | ||
| 66 | if ( i == j ) { | ||
| 67 | continue; | ||
| 68 | } | ||
| 69 | |||
| 70 | if ( nodes[i].used < nodes[j].avail ) { | ||
| 71 | ++count; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | cout << count << '\n'; | ||
| 77 | } | ||
| 78 | |||
| 79 | void | ||
| 80 | part2(const vector<Node>& nodes) | ||
| 81 | { | ||
| 82 | using pos_type = tuple<int, int>; | ||
| 83 | |||
| 84 | map<pos_type, char> grid; | ||
| 85 | |||
| 86 | #ifdef PRINT | ||
| 87 | const auto max_y = ranges::max_element(nodes, {}, &Node::y)->y; | ||
| 88 | #endif | ||
| 89 | const auto max_x = ranges::max_element(nodes, {}, &Node::x)->x; | ||
| 90 | const auto largest = ranges::max_element(nodes, {}, &Node::avail)->avail; | ||
| 91 | |||
| 92 | const pos_type g_pos = { max_x, 0 }; | ||
| 93 | const pos_type s_pos = { 0, 0 }; | ||
| 94 | |||
| 95 | pos_type start{}; | ||
| 96 | |||
| 97 | for ( const auto& node: nodes ) { | ||
| 98 | auto pos = node.pos(); | ||
| 99 | if ( pos == s_pos ) { | ||
| 100 | grid[pos] = 'S'; | ||
| 101 | } | ||
| 102 | else if ( pos == g_pos ) { | ||
| 103 | grid[pos] = 'G'; | ||
| 104 | } | ||
| 105 | else if ( node.used == 0 ) { | ||
| 106 | grid[pos] = '_'; | ||
| 107 | start = pos; | ||
| 108 | } | ||
| 109 | else if ( node.used >= largest ) { | ||
| 110 | grid[pos] = '#'; | ||
| 111 | } | ||
| 112 | else { | ||
| 113 | grid[pos] = '.'; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | #ifdef PRINT | ||
| 118 | string result{}; | ||
| 119 | for ( int pos_y = 0; pos_y <= max_y; ++pos_y ) { | ||
| 120 | for ( int pos_x = 0; pos_x <= max_x; ++pos_x ) { | ||
| 121 | result += grid[{ pos_x, pos_y }]; | ||
| 122 | } | ||
| 123 | result += '\n'; | ||
| 124 | } | ||
| 125 | |||
| 126 | cout << result << '\n'; | ||
| 127 | #endif | ||
| 128 | |||
| 129 | set<pos_type> seen; | ||
| 130 | queue<tuple<pos_type, int>> queue; // position, #Schritte | ||
| 131 | |||
| 132 | queue.emplace(start, 0); | ||
| 133 | while ( !queue.empty() ) { | ||
| 134 | const auto [pos, steps] = queue.front(); | ||
| 135 | queue.pop(); | ||
| 136 | |||
| 137 | if ( pos == g_pos ) { | ||
| 138 | cout << steps + (5 * (max_x - 1)) << '\n'; | ||
| 139 | return; | ||
| 140 | } | ||
| 141 | |||
| 142 | static const pos_type dirs[]{ { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; | ||
| 143 | |||
| 144 | for ( const auto [dx, dy]: dirs ) { | ||
| 145 | const auto [x, y] = pos; | ||
| 146 | const pos_type new_pos{ x + dx, y + dy }; | ||
| 147 | |||
| 148 | if ( !grid.contains(new_pos) || grid.at(new_pos) == '#' || seen.contains(new_pos) ) { | ||
| 149 | continue; | ||
| 150 | } | ||
| 151 | |||
| 152 | seen.insert(new_pos); | ||
| 153 | queue.emplace(new_pos, steps + 1); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | } // namespace | ||
| 159 | |||
| 160 | int | ||
| 161 | main() | ||
| 162 | { | ||
| 163 | auto nodes = readNodes("data/day22.txt"); | ||
| 164 | part1(nodes); | ||
| 165 | part2(nodes); | ||
| 166 | } | ||
