diff options
Diffstat (limited to '2016/src')
| -rw-r--r-- | 2016/src/day10.cpp | 11 | ||||
| -rw-r--r-- | 2016/src/day11.cpp | 232 |
2 files changed, 240 insertions, 3 deletions
diff --git a/2016/src/day10.cpp b/2016/src/day10.cpp index 7c1f4f9..851ad9d 100644 --- a/2016/src/day10.cpp +++ b/2016/src/day10.cpp | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #include <filesystem> | ||
| 1 | #include <fstream> | 2 | #include <fstream> |
| 2 | #include <iostream> | 3 | #include <iostream> |
| 3 | #include <map> | 4 | #include <map> |
| @@ -9,6 +10,8 @@ using namespace std; | |||
| 9 | 10 | ||
| 10 | using Sink = tuple<string, int>; | 11 | using Sink = tuple<string, int>; |
| 11 | 12 | ||
| 13 | namespace { | ||
| 14 | |||
| 12 | vector<string> | 15 | vector<string> |
| 13 | split(const string& line, char sep) | 16 | split(const string& line, char sep) |
| 14 | { | 17 | { |
| @@ -23,7 +26,7 @@ split(const string& line, char sep) | |||
| 23 | } | 26 | } |
| 24 | 27 | ||
| 25 | map<int, tuple<Sink, Sink, vector<int>>> | 28 | map<int, tuple<Sink, Sink, vector<int>>> |
| 26 | read_file(string_view filename) | 29 | read_file(const filesystem::path& filename) |
| 27 | { | 30 | { |
| 28 | fstream input{ filename }; | 31 | fstream input{ filename }; |
| 29 | 32 | ||
| @@ -84,16 +87,18 @@ solve(map<int, tuple<Sink, Sink, vector<int>>> bots) | |||
| 84 | 87 | ||
| 85 | // part1 | 88 | // part1 |
| 86 | if ( chips.at(0) == 17 && chips.at(1) == 61 ) { | 89 | if ( chips.at(0) == 17 && chips.at(1) == 61 ) { |
| 87 | cout << id << endl; | 90 | cout << id << '\n'; |
| 88 | } | 91 | } |
| 89 | 92 | ||
| 90 | chips.clear(); | 93 | chips.clear(); |
| 91 | } | 94 | } |
| 92 | 95 | ||
| 93 | // part2 | 96 | // part2 |
| 94 | cout << outputs[0] * outputs[1] * outputs[2] << endl; | 97 | cout << outputs[0] * outputs[1] * outputs[2] << '\n'; |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 100 | } // namespace | ||
| 101 | |||
| 97 | int | 102 | int |
| 98 | main() | 103 | main() |
| 99 | { | 104 | { |
diff --git a/2016/src/day11.cpp b/2016/src/day11.cpp new file mode 100644 index 0000000..af3d2df --- /dev/null +++ b/2016/src/day11.cpp | |||
| @@ -0,0 +1,232 @@ | |||
| 1 | #include <fstream> | ||
| 2 | #include <iostream> | ||
| 3 | #include <map> | ||
| 4 | #include <set> | ||
| 5 | #include <sstream> | ||
| 6 | #include <string> | ||
| 7 | |||
| 8 | using namespace std; | ||
| 9 | |||
| 10 | struct Item { | ||
| 11 | Item() = default; | ||
| 12 | Item(size_t chip_floor, size_t generator_floor) // NOLINT | ||
| 13 | : chip_floor_{ chip_floor } | ||
| 14 | , generator_floor_{ generator_floor } | ||
| 15 | { | ||
| 16 | } | ||
| 17 | |||
| 18 | size_t chip_floor_; | ||
| 19 | size_t generator_floor_; | ||
| 20 | |||
| 21 | bool operator<(const Item& rhs) const | ||
| 22 | { | ||
| 23 | if ( chip_floor_ != rhs.chip_floor_ ) { | ||
| 24 | return chip_floor_ < rhs.chip_floor_; | ||
| 25 | } | ||
| 26 | return generator_floor_ < rhs.generator_floor_; | ||
| 27 | } | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct State { | ||
| 31 | explicit State(const vector<Item>& items) | ||
| 32 | : items_{ items } | ||
| 33 | { | ||
| 34 | } | ||
| 35 | |||
| 36 | [[nodiscard]] | ||
| 37 | bool is_valid() const | ||
| 38 | { | ||
| 39 | for ( size_t i = 0; i != items_.size(); ++i ) { | ||
| 40 | const auto chip_floor = items_[i].chip_floor_; // Etage des Mikrochips | ||
| 41 | if ( chip_floor == items_[i].generator_floor_ ) { | ||
| 42 | continue; // Mikrochip ist mit seinem Generator zusammen | ||
| 43 | } | ||
| 44 | // Prüfe, ob ein fremder Generator auf derselben Etage ist | ||
| 45 | for ( size_t j = 0; j != items_.size(); ++j ) { | ||
| 46 | if ( j != i && chip_floor == items_[j].generator_floor_ ) { | ||
| 47 | return false; // Ungültig: Mikrochip mit fremdem Generator ohne eigenen Generator | ||
| 48 | } | ||
| 49 | } | ||
| 50 | } | ||
| 51 | return true; | ||
| 52 | } | ||
| 53 | |||
| 54 | [[nodiscard]] | ||
| 55 | bool is_goal() const | ||
| 56 | { | ||
| 57 | for ( const auto& item: items_ ) { | ||
| 58 | if ( item.chip_floor_ != 3 || item.generator_floor_ != 3 ) { | ||
| 59 | return false; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | return elevator_ == 3; | ||
| 63 | } | ||
| 64 | |||
| 65 | bool operator<(const State& rhs) const | ||
| 66 | { | ||
| 67 | if ( elevator_ != rhs.elevator_ ) { | ||
| 68 | return elevator_ < rhs.elevator_; | ||
| 69 | } | ||
| 70 | return items_ < rhs.items_; | ||
| 71 | } | ||
| 72 | |||
| 73 | size_t elevator_{}; | ||
| 74 | vector<Item> items_; | ||
| 75 | }; | ||
| 76 | |||
| 77 | namespace { | ||
| 78 | |||
| 79 | set<string> | ||
| 80 | split(const string& line, char sep) | ||
| 81 | { | ||
| 82 | set<string> parts; | ||
| 83 | stringstream input{ line }; | ||
| 84 | |||
| 85 | for ( string part; getline(input, part, sep); ) { | ||
| 86 | parts.insert(part); | ||
| 87 | } | ||
| 88 | |||
| 89 | for ( const auto& word: { "The", "a", "floor", "and", "contains", "microchip", | ||
| 90 | "microchip.", "microchip,", "generator", "generator.", "generator,", "first", | ||
| 91 | "second", "third", "fourth", "nothing", "relevant." } ) { | ||
| 92 | parts.erase(word); | ||
| 93 | } | ||
| 94 | |||
| 95 | return parts; | ||
| 96 | } | ||
| 97 | |||
| 98 | vector<Item> | ||
| 99 | read_file(const filesystem::path& filename) | ||
| 100 | { | ||
| 101 | fstream input{ filename }; | ||
| 102 | map<string, Item> data; | ||
| 103 | |||
| 104 | auto is_microchip = [](string_view item) { | ||
| 105 | return item.ends_with("-compatible"); | ||
| 106 | }; | ||
| 107 | |||
| 108 | string line; | ||
| 109 | for ( size_t floor = 0; getline(input, line); ++floor ) { | ||
| 110 | auto items = split(line, ' '); | ||
| 111 | |||
| 112 | for ( auto item: items ) { | ||
| 113 | if ( is_microchip(item) ) { | ||
| 114 | item = item.erase(item.find('-')); | ||
| 115 | |||
| 116 | data[item].chip_floor_ = floor; | ||
| 117 | } | ||
| 118 | else { | ||
| 119 | data[item].generator_floor_ = floor; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | vector<Item> result; | ||
| 125 | result.reserve(data.size()); | ||
| 126 | for ( const auto& item: data ) { | ||
| 127 | result.emplace_back(item.second); | ||
| 128 | } | ||
| 129 | |||
| 130 | return result; | ||
| 131 | } | ||
| 132 | |||
| 133 | int | ||
| 134 | part1(const State& initial) | ||
| 135 | { | ||
| 136 | queue<pair<State, int>> queue; // {Zustand, Schritte} | ||
| 137 | set<State> visited; | ||
| 138 | |||
| 139 | queue.emplace(initial, 0); | ||
| 140 | visited.insert(initial); | ||
| 141 | |||
| 142 | while ( !queue.empty() ) { | ||
| 143 | auto [current, steps] = queue.front(); | ||
| 144 | queue.pop(); | ||
| 145 | |||
| 146 | if ( current.is_goal() ) { | ||
| 147 | return steps; | ||
| 148 | } | ||
| 149 | |||
| 150 | // Mögliche Aufzugbewegungen: hoch oder runter | ||
| 151 | for ( int dir: { -1, 1 } ) { | ||
| 152 | auto new_elevator = current.elevator_ + size_t(dir); | ||
| 153 | if ( new_elevator < 0 || new_elevator > 3 ) { | ||
| 154 | continue; | ||
| 155 | } | ||
| 156 | |||
| 157 | // Wähle 1 oder 2 Objekte | ||
| 158 | vector<size_t> items_on_floor; | ||
| 159 | for ( size_t i = 0; i < current.items_.size(); ++i ) { | ||
| 160 | if ( current.items_[i].generator_floor_ == current.elevator_ ) { | ||
| 161 | items_on_floor.emplace_back(i * 2); // Generator | ||
| 162 | } | ||
| 163 | if ( current.items_[i].chip_floor_ == current.elevator_ ) { | ||
| 164 | items_on_floor.emplace_back((i * 2) + 1); // Mikrochip | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | // Alle Kombinationen von 1 oder 2 Objekten | ||
| 169 | for ( size_t i = 0; i < items_on_floor.size(); ++i ) { | ||
| 170 | // 1 Objekt | ||
| 171 | State next = current; | ||
| 172 | next.elevator_ = new_elevator; | ||
| 173 | auto item = items_on_floor[i]; | ||
| 174 | if ( item % 2 == 0 ) { | ||
| 175 | next.items_[item / 2].generator_floor_ = new_elevator; // Generator | ||
| 176 | } | ||
| 177 | else { | ||
| 178 | next.items_[item / 2].chip_floor_ = new_elevator; // Mikrochip | ||
| 179 | } | ||
| 180 | if ( next.is_valid() && !visited.contains(next) ) { | ||
| 181 | visited.emplace(next); | ||
| 182 | queue.emplace(next, steps + 1); | ||
| 183 | } | ||
| 184 | |||
| 185 | // 2 Objekte | ||
| 186 | for ( size_t j = i + 1; j < items_on_floor.size(); ++j ) { | ||
| 187 | State next2 = current; | ||
| 188 | next2.elevator_ = new_elevator; | ||
| 189 | auto item1 = items_on_floor[i]; | ||
| 190 | auto item2 = items_on_floor[j]; | ||
| 191 | if ( item1 % 2 == 0 ) { | ||
| 192 | next2.items_[item1 / 2].generator_floor_ = new_elevator; | ||
| 193 | } | ||
| 194 | else { | ||
| 195 | next2.items_[item1 / 2].chip_floor_ = new_elevator; | ||
| 196 | } | ||
| 197 | if ( item2 % 2 == 0 ) { | ||
| 198 | next2.items_[item2 / 2].generator_floor_ = new_elevator; | ||
| 199 | } | ||
| 200 | else { | ||
| 201 | next2.items_[item2 / 2].chip_floor_ = new_elevator; | ||
| 202 | } | ||
| 203 | if ( next2.is_valid() && !visited.contains(next2) ) { | ||
| 204 | visited.insert(next2); | ||
| 205 | queue.emplace(next2, steps + 1); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | return -1; // Keine Lösung gefunden | ||
| 212 | } | ||
| 213 | |||
| 214 | int | ||
| 215 | part2(State initial) | ||
| 216 | { | ||
| 217 | initial.items_.emplace_back(0, 0); | ||
| 218 | initial.items_.emplace_back(0, 0); | ||
| 219 | return part1(initial); | ||
| 220 | } | ||
| 221 | |||
| 222 | } // namespace | ||
| 223 | |||
| 224 | int | ||
| 225 | main() | ||
| 226 | { | ||
| 227 | auto floors = read_file("data/day11.txt"); | ||
| 228 | State state{ floors }; | ||
| 229 | |||
| 230 | cout << "Part1: " << part1(state) << '\n'; | ||
| 231 | cout << "Part2: " << part2(state) << '\n'; | ||
| 232 | } | ||
