Completed puzzles for 2021 day 23

This commit is contained in:
2022-01-12 14:26:21 +00:00
parent 3ba00ad3eb
commit 1fab8c9161
3 changed files with 396 additions and 205 deletions

View File

@@ -83,12 +83,12 @@ auto dijkstra(Node const& initial, Cost initial_cost, TransitionManager transiti
/** \c nodes maintains a map of all the nodes we've visited or want to visit. Nodes that cost
* less than the current cost at the front of costs have been visited. The rest haven't.
*/
std::map<Node const*, std::pair<Cost, Node const*>, NodePCmp> nodes;
std::map<Node const*, Cost, NodePCmp> nodes;
/** \c costs maintains a map of costs to the nodes that cost that much to visit. */
std::map<Cost, std::unordered_set<Node const*>> costs;
Cost current_cost{initial_cost};
Node const* current_node{new Node(initial)};
nodes.insert({current_node, {current_cost, nullptr}});
nodes.insert({current_node, current_cost});
costs.insert({current_cost, {current_node}});
/* Helper lambda to clean up after ourselves. */
@@ -99,29 +99,28 @@ auto dijkstra(Node const& initial, Cost initial_cost, TransitionManager transiti
};
/* Helper lambda to insert into the maps. */
auto inserter = [&costs, &nodes, &current_node, &current_cost](Node const& node, Cost cost) {
auto inserter = [&costs, &nodes, &current_cost](Node const& node, Cost cost) {
cost += current_cost;
auto node_it{nodes.find(&node)};
/* Skip inserting nodes we've already visited, or that would cost more to visit. */
if (node_it != nodes.end() && node_it->second.first <= cost) {
if (node_it != nodes.end() && node_it->second <= cost) {
return;
}
Node const* nodep{nullptr};
if (node_it == nodes.end()) {
nodep = new Node(node);
nodes.insert({nodep, {cost, current_node}});
nodes.insert({nodep, cost});
}
else {
/* Node has a cheaper cost than we thought: Remove the node from its old cost list */
nodep = node_it->first;
auto cost_it{costs.find(node_it->second.first)};
auto cost_it{costs.find(node_it->second)};
assert(cost_it != costs.end());
cost_it->second.erase(nodep);
/* Now update the cost in the nodes map and use the nodep as the node pointer. */
node_it->second.first = cost;
node_it->second.second = current_node;
node_it->second = cost;
}
auto [cost_it, success] = costs.insert({cost, {}});
@@ -137,7 +136,6 @@ auto dijkstra(Node const& initial, Cost initial_cost, TransitionManager transiti
return a + c.second.size();
}) == nodes.size() - iter);
for (auto& nodep : cost_it->second) {
current_node = nodep;
if (iter++ % 100'000 == 0) {
std::cout << "Iteration: " << iter << " cost " << current_cost
<< " total number of nodes: " << nodes.size()
@@ -146,13 +144,6 @@ auto dijkstra(Node const& initial, Cost initial_cost, TransitionManager transiti
}
if (transition_manager.is_finished(*nodep)) {
auto result{std::make_pair(*nodep, current_cost)};
/* Print the backtrace. */
Node const* n{nodep};
while (n != nullptr) {
auto node_it{nodes.find(n)};
std::cout << "Cost: " << node_it->second.first << ":\n" << *n;
n = node_it->second.second;
}
cleanup(nodes);
return result;
}