diff --git a/2021/graph-utils.h b/2021/graph-utils.h index be60678..250c445 100644 --- a/2021/graph-utils.h +++ b/2021/graph-utils.h @@ -83,10 +83,13 @@ 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 nodes; + std::map, NodePCmp> nodes; /** \c costs maintains a map of costs to the nodes that cost that much to visit. */ std::map> costs; - Cost current_cost{std::numeric_limits::min()}; + Cost current_cost{initial_cost}; + Node const* current_node{new Node(initial)}; + nodes.insert({current_node, {current_cost, nullptr}}); + costs.insert({current_cost, {current_node}}); /* Helper lambda to clean up after ourselves. */ auto cleanup = [](auto& nodes) { @@ -96,38 +99,35 @@ auto dijkstra(Node const& initial, Cost initial_cost, TransitionManager transiti }; /* Helper lambda to insert into the maps. */ - auto inserter = [&costs, &nodes, ¤t_cost](Node const& node, Cost cost) { + auto inserter = [&costs, &nodes, ¤t_node, ¤t_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 <= cost) { + if (node_it != nodes.end() && node_it->second.first <= cost) { return; } Node const* nodep{nullptr}; if (node_it == nodes.end()) { nodep = new Node(node); - nodes.insert({nodep, cost}); + nodes.insert({nodep, {cost, current_node}}); } 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)}; + auto cost_it{costs.find(node_it->second.first)}; 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 = cost; + node_it->second.first = cost; + node_it->second.second = current_node; } auto [cost_it, success] = costs.insert({cost, {}}); cost_it->second.insert(nodep); }; - Node* init{new Node(initial)}; - nodes.insert({init, initial_cost}); - costs.insert({initial_cost, {init}}); - std::uint64_t iter{0}; while (!costs.empty()) { auto cost_it{costs.begin()}; @@ -137,6 +137,7 @@ 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() @@ -145,6 +146,13 @@ 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; } diff --git a/2021/puzzle-23-01.cc b/2021/puzzle-23-01.cc index c4d1715..c92a7e0 100644 --- a/2021/puzzle-23-01.cc +++ b/2021/puzzle-23-01.cc @@ -169,6 +169,18 @@ private: std::array State::finished_ = {'.', '.', '.', '.', '.', '.', '.', 'A', 'B', 'C', 'D', 'A', 'B', 'C', 'D'}; +std::ostream& operator<<(std::ostream& os, State const& s) +{ + os << "#############\n" + << '#' << s.node(0) << s.node(1) << '.' << s.node(2) << '.' << s.node(3) << '.' << s.node(4) + << '.' << s.node(5) << s.node(6) << "#\n" + << "###" << s.node(7) << '#' << s.node(8) << '#' << s.node(9) << '#' << s.node(10) << "###\n" + << " #" << s.node(11) << '#' << s.node(12) << '#' << s.node(13) << '#' << s.node(14) << "#\n" + << " #########\n"; + + return os; +} + struct StateTranstitionManager { bool is_finished(State const& state) { return state.finished(); } diff --git a/2021/puzzle-23-02.cc b/2021/puzzle-23-02.cc index c68621a..504295a 100644 --- a/2021/puzzle-23-02.cc +++ b/2021/puzzle-23-02.cc @@ -191,6 +191,20 @@ std::array State::finished_ = {'.', '.', '.', '.', '.', '.', 'B', 'C', 'D', 'A', 'B', 'C', 'D', 'A', 'B', 'C', 'D', 'A', 'B', 'C', 'D'}; + +std::ostream& operator<<(std::ostream& os, State const& s) +{ + os << "#############\n" + << '#' << s.node(0) << s.node(1) << '.' << s.node(2) << '.' << s.node(3) << '.' << s.node(4) + << '.' << s.node(5) << s.node(6) << "#\n" + << "###" << s.node(7) << '#' << s.node(8) << '#' << s.node(9) << '#' << s.node(10) << "###\n" + << " #" << s.node(11) << '#' << s.node(12) << '#' << s.node(13) << '#' << s.node(14) << "#\n" + << " #" << s.node(15) << '#' << s.node(16) << '#' << s.node(17) << '#' << s.node(18) << "#\n" + << " #" << s.node(19) << '#' << s.node(20) << '#' << s.node(21) << '#' << s.node(22) << "#\n" + << " #########\n"; + + return os; +} struct StateTranstitionManager { bool is_finished(State const& state) { return state.finished(); }