18
This commit is contained in:
parent
bfe57e4487
commit
262c339920
56
2019/18.cpp
56
2019/18.cpp
|
@ -94,7 +94,7 @@ auto FindDistances(Map const& map, Features const& features) -> Distances {
|
||||||
Distances distances;
|
Distances distances;
|
||||||
|
|
||||||
for (auto && [start_letter, start_coord] : features) {
|
for (auto && [start_letter, start_coord] : features) {
|
||||||
if (islower(start_letter) || start_letter == '@') {
|
if (!std::isupper(start_letter)) {
|
||||||
FindDistancesFrom(map, features, distances, start_letter, start_coord);
|
FindDistancesFrom(map, features, distances, start_letter, start_coord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,12 +102,6 @@ auto FindDistances(Map const& map, Features const& features) -> Distances {
|
||||||
return distances;
|
return distances;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct P1S {
|
|
||||||
char location;
|
|
||||||
unsigned long long keys;
|
|
||||||
auto operator<=>(P1S const&) const = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto HasKey(Doors doors, char key) {
|
auto HasKey(Doors doors, char key) {
|
||||||
return doors.test(std::toupper(key) - 'A');
|
return doors.test(std::toupper(key) - 'A');
|
||||||
}
|
}
|
||||||
|
@ -116,26 +110,31 @@ auto SetKey(Doors doors, char key) {
|
||||||
return doors.set(std::toupper(key) - 'A');
|
return doors.set(std::toupper(key) - 'A');
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Part1(Distances const& distances) -> std::int64_t {
|
auto SolveMaze(Distances const& distances, std::set<char> const initial_locations) -> std::int64_t {
|
||||||
std::set<P1S> seen;
|
// Track current positions and current set of keys in easy to compare form
|
||||||
std::multimap<std::int64_t, std::pair<char, Doors>> todo
|
using Visited = std::pair<std::set<char>, unsigned long long>;
|
||||||
{{0, {'@', Doors()}}};
|
std::set<Visited> seen;
|
||||||
|
|
||||||
|
std::multimap<std::int64_t, std::pair<std::set<char>, Doors>> todo
|
||||||
|
{{0, {initial_locations, Doors()}}};
|
||||||
|
|
||||||
while (!todo.empty()) {
|
while (!todo.empty()) {
|
||||||
auto it = todo.begin();
|
auto it = todo.begin();
|
||||||
auto [steps, ld] = *it;
|
auto [steps, ld] = *it;
|
||||||
auto& [l,keys] = ld;
|
auto& [locations,keys] = ld;
|
||||||
todo.erase(it);
|
todo.erase(it);
|
||||||
|
|
||||||
if (keys.all()) { return steps; }
|
if (keys.all()) { return steps; }
|
||||||
|
|
||||||
if (seen.insert({l,keys.to_ullong()}).second) {
|
if (seen.insert({locations,keys.to_ullong()}).second) {
|
||||||
auto dit = distances.find(l);
|
for (auto location : locations) {
|
||||||
if (dit != distances.end()) {
|
auto locations1 = locations; locations1.erase(location);
|
||||||
for (auto && [next, costneed] : dit->second) {
|
|
||||||
|
for (auto && [next, costneed] : distances.at(location)) {
|
||||||
auto [cost, need] = costneed;
|
auto [cost, need] = costneed;
|
||||||
if ((need & (~keys)).none()) {
|
if ((need & ~keys).none()) {
|
||||||
todo.insert({steps + cost, {next, SetKey(keys, next)}});
|
auto locations2 = locations1; locations2.insert(next);
|
||||||
|
todo.insert({steps + cost, {locations2, SetKey(keys, next)}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,6 +144,20 @@ auto Part1(Distances const& distances) -> std::int64_t {
|
||||||
throw std::runtime_error{"no solution to part 1"};
|
throw std::runtime_error{"no solution to part 1"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto UpdateMap(Map& map, Features & features) {
|
||||||
|
auto start = features['@'];
|
||||||
|
map[start.y][start.x] = '#';
|
||||||
|
map[start.y][start.x+1] = '#';
|
||||||
|
map[start.y][start.x-1] = '#';
|
||||||
|
map[start.y+1][start.x] = '#';
|
||||||
|
map[start.y-1][start.x] = '#';
|
||||||
|
features.erase('@');
|
||||||
|
features['^'] = Up(Left(start));
|
||||||
|
features['&'] = Down(Left(start));
|
||||||
|
features['*'] = Up(Right(start));
|
||||||
|
features['$'] = Down(Right(start));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
auto main(int argc, char** argv) -> int {
|
auto main(int argc, char** argv) -> int {
|
||||||
|
@ -152,6 +165,9 @@ auto main(int argc, char** argv) -> int {
|
||||||
auto features = FindFeatures(map);
|
auto features = FindFeatures(map);
|
||||||
auto distances = FindDistances(map, features);
|
auto distances = FindDistances(map, features);
|
||||||
|
|
||||||
std::cout << "Part 1: " << Part1(distances) << std::endl;
|
std::cout << "Part 1: " << SolveMaze(distances, {'@'}) << std::endl;
|
||||||
//std::cout << "Part 2: " << part2 << std::endl;
|
|
||||||
|
UpdateMap(map, features);
|
||||||
|
distances = FindDistances(map, features);
|
||||||
|
std::cout << "Part 2: " << SolveMaze(distances, {'^', '&', '*', '$'}) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user