From 1fab8c916136cf19e9c88d4bf9986ba9d506acb3 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Wed, 12 Jan 2022 14:26:21 +0000 Subject: [PATCH] Completed puzzles for 2021 day 23 --- 2021/graph-utils.h | 23 +-- 2021/puzzle-23-01.cc | 221 ++++++++++++++++----------- 2021/puzzle-23-02.cc | 357 ++++++++++++++++++++++++++++++------------- 3 files changed, 396 insertions(+), 205 deletions(-) diff --git a/2021/graph-utils.h b/2021/graph-utils.h index 250c445..d209624 100644 --- a/2021/graph-utils.h +++ b/2021/graph-utils.h @@ -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, NodePCmp> nodes; + std::map nodes; /** \c costs maintains a map of costs to the nodes that cost that much to visit. */ std::map> 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, ¤t_node, ¤t_cost](Node const& node, Cost cost) { + auto inserter = [&costs, &nodes, ¤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.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; } diff --git a/2021/puzzle-23-01.cc b/2021/puzzle-23-01.cc index c92a7e0..c3de984 100644 --- a/2021/puzzle-23-01.cc +++ b/2021/puzzle-23-01.cc @@ -32,17 +32,121 @@ using Position = char; using UInt = int; using Type = char; -std::multimap> valid_moves{ - {0, {7, 3}}, {0, {8, 5}}, {0, {9, 7}}, {0, {10, 9}}, {1, {7, 2}}, {1, {8, 4}}, {1, {9, 6}}, - {1, {10, 8}}, {2, {7, 2}}, {2, {8, 2}}, {2, {9, 4}}, {2, {10, 6}}, {3, {7, 4}}, {3, {8, 2}}, - {3, {9, 2}}, {3, {10, 4}}, {4, {7, 6}}, {4, {8, 4}}, {4, {9, 2}}, {4, {10, 2}}, {5, {7, 8}}, - {5, {8, 6}}, {5, {9, 4}}, {5, {10, 2}}, {6, {7, 9}}, {6, {8, 7}}, {6, {9, 5}}, {6, {10, 3}}, - {7, {0, 3}}, {7, {1, 2}}, {7, {2, 2}}, {7, {3, 4}}, {7, {4, 6}}, {7, {5, 8}}, {7, {6, 9}}, - {7, {11, 1}}, {8, {0, 5}}, {8, {1, 4}}, {8, {2, 2}}, {8, {3, 2}}, {8, {4, 4}}, {8, {5, 6}}, - {8, {6, 7}}, {8, {12, 1}}, {9, {0, 7}}, {9, {1, 6}}, {9, {2, 4}}, {9, {3, 2}}, {9, {4, 2}}, - {9, {5, 4}}, {9, {6, 5}}, {9, {13, 1}}, {10, {0, 9}}, {10, {1, 8}}, {10, {2, 6}}, {10, {3, 4}}, - {10, {4, 2}}, {10, {5, 2}}, {10, {6, 3}}, {10, {14, 1}}, {11, {7, 1}}, {12, {8, 1}}, {13, {9, 1}}, - {14, {10, 1}}}; +std::multimap, UInt>> valid_moves{ + {0, {{1, 7}, 3}}, + {0, {{1, 2, 8}, 5}}, + {0, {{1, 2, 3, 9}, 7}}, + {0, {{1, 2, 3, 4, 10}, 9}}, + {0, {{1, 7, 11}, 4}}, + {0, {{1, 2, 8, 12}, 6}}, + {0, {{1, 2, 3, 9, 13}, 8}}, + {0, {{1, 2, 3, 4, 10, 14}, 10}}, + {1, {{7}, 2}}, + {1, {{2, 8}, 4}}, + {1, {{2, 3, 9}, 6}}, + {1, {{2, 3, 4, 10}, 8}}, + {1, {{7, 11}, 3}}, + {1, {{2, 8, 12}, 5}}, + {1, {{2, 3, 9, 13}, 7}}, + {1, {{2, 3, 4, 10, 14}, 9}}, + {2, {{7}, 2}}, + {2, {{8}, 2}}, + {2, {{3, 9}, 4}}, + {2, {{3, 4, 10}, 6}}, + {2, {{7, 11}, 3}}, + {2, {{8, 12}, 3}}, + {2, {{3, 9, 13}, 5}}, + {2, {{3, 4, 10, 14}, 7}}, + {3, {{2, 7}, 4}}, + {3, {{8}, 2}}, + {3, {{9}, 2}}, + {3, {{4, 10}, 4}}, + {3, {{2, 7, 11}, 5}}, + {3, {{8, 12}, 3}}, + {3, {{9, 13}, 3}}, + {3, {{4, 10, 14}, 5}}, + {4, {{3, 2, 7}, 6}}, + {4, {{3, 8}, 4}}, + {4, {{9}, 2}}, + {4, {{10}, 2}}, + {4, {{3, 2, 7, 11}, 7}}, + {4, {{3, 8, 12}, 5}}, + {4, {{9, 13}, 3}}, + {4, {{10, 14}, 3}}, + {5, {{4, 3, 2, 7}, 8}}, + {5, {{4, 3, 8}, 6}}, + {5, {{4, 9}, 4}}, + {5, {{10}, 2}}, + {5, {{4, 3, 2, 7, 11}, 9}}, + {5, {{4, 3, 8, 12}, 7}}, + {5, {{4, 9, 13}, 5}}, + {5, {{10, 14}, 3}}, + {6, {{5, 4, 3, 2, 7}, 9}}, + {6, {{5, 4, 3, 8}, 7}}, + {6, {{5, 4, 9}, 5}}, + {6, {{5, 10}, 3}}, + {6, {{5, 4, 3, 2, 7, 11}, 10}}, + {6, {{5, 4, 3, 8, 12}, 8}}, + {6, {{5, 4, 9, 13}, 6}}, + {6, {{5, 10, 14}, 4}}, + + {7, {{1, 0}, 3}}, + {7, {{1}, 2}}, + {7, {{2}, 2}}, + {7, {{2, 3}, 4}}, + {7, {{2, 3, 4}, 6}}, + {7, {{2, 3, 4, 5}, 8}}, + {7, {{2, 3, 4, 5, 6}, 9}}, + {8, {{2, 1, 0}, 5}}, + {8, {{2, 1}, 4}}, + {8, {{2}, 2}}, + {8, {{3}, 2}}, + {8, {{3, 4}, 4}}, + {8, {{3, 4, 5}, 6}}, + {8, {{3, 4, 5, 6}, 7}}, + {9, {{3, 2, 1, 0}, 7}}, + {9, {{3, 2, 1}, 6}}, + {9, {{3, 2}, 4}}, + {9, {{3}, 2}}, + {9, {{4}, 2}}, + {9, {{4, 5}, 4}}, + {9, {{4, 5, 6}, 5}}, + {10, {{4, 3, 2, 1, 0}, 9}}, + {10, {{4, 3, 2, 1}, 8}}, + {10, {{4, 3, 2}, 6}}, + {10, {{4, 3}, 4}}, + {10, {{4}, 2}}, + {10, {{5}, 2}}, + {10, {{5, 6}, 3}}, + {11, {{7, 1, 0}, 4}}, + {11, {{7, 1}, 3}}, + {11, {{7, 2}, 3}}, + {11, {{7, 2, 3}, 5}}, + {11, {{7, 2, 3, 4}, 7}}, + {11, {{7, 2, 3, 4, 5}, 9}}, + {11, {{7, 2, 3, 4, 5, 6}, 10}}, + {12, {{8, 2, 1, 0}, 6}}, + {12, {{8, 2, 1}, 5}}, + {12, {{8, 2}, 3}}, + {12, {{8, 3}, 3}}, + {12, {{8, 3, 4}, 5}}, + {12, {{8, 3, 4, 5}, 7}}, + {12, {{8, 3, 4, 5, 6}, 8}}, + {13, {{9, 3, 2, 1, 0}, 8}}, + {13, {{9, 3, 2, 1}, 7}}, + {13, {{9, 3, 2}, 5}}, + {13, {{9, 3}, 3}}, + {13, {{9, 4}, 3}}, + {13, {{9, 4, 5}, 5}}, + {13, {{9, 4, 5, 6}, 7}}, + {14, {{10, 4, 3, 2, 1, 0}, 10}}, + {14, {{10, 4, 3, 2, 1}, 9}}, + {14, {{10, 4, 3, 2}, 7}}, + {14, {{10, 4, 3}, 5}}, + {14, {{10, 4}, 3}}, + {14, {{10, 5}, 3}}, + {14, {{10, 5, 6}, 4}}, +}; std::map multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}}; @@ -56,18 +160,6 @@ struct State bool check_move(unsigned from, unsigned to) { - if (from < 7) { - assert(to > 6 && to < 11); - } - else if (from > 6 & from < 11) { - assert(to < 7 || (to > 10 && to < 15)); - } - else if (from > 10 && from < 15) { - assert(to > 6 && to < 11); - } - else { - assert(false); - } if (nodes_[from] == '.' || nodes_[to] != '.') { return false; } @@ -76,72 +168,22 @@ struct State return nodes_[from] != finished_[from]; } if (from > 6 && from < 11) { - if (to > 10) { - // Only move into bottom position if we're moving the correct piece. - return nodes_[from] == finished_[to]; - } - // Moving to top row - if (to == 0 && nodes_[1] != '.') { - return false; - } - if (to < 2 && from > 7 && nodes_[2] != '.') { - return false; - } - if (to < 3 && from > 8 && nodes_[3] != '.') { - return false; - } - if (to < 4 && from > 9 && nodes_[4] != '.') { - return false; - } - - if (to == 6 && nodes_[5] != '.') { - return false; - } - if (to > 4 && from < 10 && nodes_[4] != '.') { - return false; - } - if (to > 3 && from < 9 && nodes_[3] != '.') { - return false; - } - if (to > 2 && from < 8 && nodes_[2] != '.') { - return false; - } - - return true; + // Only move out of the bottom row if we or the node below us is not meant to be there. + return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from]; } if (from < 7) { - // Can only move down if we're the right type. if (nodes_[from] != finished_[to]) { return false; } - - // Now encode the rules about moving along the top. - if (from == 0 && nodes_[1] != '.') { - return false; + while (to > 10) { + to -= 4; } - if (from < 2 && to > 7 && nodes_[2] != '.') { - return false; + while (to < 15) { + if (nodes_[to] != '.' && nodes_[to] != finished_[to]) { + return false; + } + to += 4; } - if (from < 3 && to > 8 && nodes_[3] != '.') { - return false; - } - if (from < 4 && to > 9 && nodes_[4] != '.') { - return false; - } - - if (from == 6 && nodes_[5] != '.') { - return false; - } - if (from > 4 && to < 10 && nodes_[4] != '.') { - return false; - } - if (from > 3 && to < 9 && nodes_[3] != '.') { - return false; - } - if (from > 2 && to < 8 && nodes_[2] != '.') { - return false; - } - return true; } abort(); @@ -196,9 +238,18 @@ struct StateTranstitionManager auto [it_begin, it_end] = valid_moves.equal_range(i); for (auto move_it{it_begin}; move_it != it_end; ++move_it) { State next_state(state); - UInt cost_delta = move_it->second.second * multipliers[state.node(i)]; - if (next_state.move(i, move_it->second.first, cost_delta)) { - inserter(next_state, cost_delta); + bool cont = true; + for (auto pos_it : move_it->second.first) { + if (state.node(pos_it) != '.') { + cont = false; + break; + } + } + if (cont) { + UInt cost_delta = move_it->second.second * multipliers[state.node(i)]; + if (next_state.move(i, move_it->second.first.back(), cost_delta)) { + inserter(next_state, cost_delta); + } } } } diff --git a/2021/puzzle-23-02.cc b/2021/puzzle-23-02.cc index 504295a..b4abd69 100644 --- a/2021/puzzle-23-02.cc +++ b/2021/puzzle-23-02.cc @@ -38,21 +38,233 @@ using Position = char; using UInt = int; using Type = char; -std::multimap> valid_moves{ - {0, {7, 3}}, {0, {8, 5}}, {0, {9, 7}}, {0, {10, 9}}, {1, {7, 2}}, {1, {8, 4}}, - {1, {9, 6}}, {1, {10, 8}}, {2, {7, 2}}, {2, {8, 2}}, {2, {9, 4}}, {2, {10, 6}}, - {3, {7, 4}}, {3, {8, 2}}, {3, {9, 2}}, {3, {10, 4}}, {4, {7, 6}}, {4, {8, 4}}, - {4, {9, 2}}, {4, {10, 2}}, {5, {7, 8}}, {5, {8, 6}}, {5, {9, 4}}, {5, {10, 2}}, - {6, {7, 9}}, {6, {8, 7}}, {6, {9, 5}}, {6, {10, 3}}, {7, {0, 3}}, {7, {1, 2}}, - {7, {2, 2}}, {7, {3, 4}}, {7, {4, 6}}, {7, {5, 8}}, {7, {6, 9}}, {7, {11, 1}}, - {8, {0, 5}}, {8, {1, 4}}, {8, {2, 2}}, {8, {3, 2}}, {8, {4, 4}}, {8, {5, 6}}, - {8, {6, 7}}, {8, {12, 1}}, {9, {0, 7}}, {9, {1, 6}}, {9, {2, 4}}, {9, {3, 2}}, - {9, {4, 2}}, {9, {5, 4}}, {9, {6, 5}}, {9, {13, 1}}, {10, {0, 9}}, {10, {1, 8}}, - {10, {2, 6}}, {10, {3, 4}}, {10, {4, 2}}, {10, {5, 2}}, {10, {6, 3}}, {10, {14, 1}}, - {11, {7, 1}}, {12, {8, 1}}, {13, {9, 1}}, {14, {10, 1}}, {11, {15, 1}}, {12, {16, 1}}, - {13, {17, 1}}, {14, {18, 1}}, {15, {11, 1}}, {16, {12, 1}}, {17, {13, 1}}, {18, {14, 1}}, - {15, {19, 1}}, {16, {20, 1}}, {17, {21, 1}}, {18, {22, 1}}, {19, {15, 1}}, {20, {16, 1}}, - {21, {17, 1}}, {22, {18, 1}}}; +std::multimap, UInt>> valid_moves{ + {0, {{1, 7}, 3}}, + {0, {{1, 2, 8}, 5}}, + {0, {{1, 2, 3, 9}, 7}}, + {0, {{1, 2, 3, 4, 10}, 9}}, + {0, {{1, 7, 11}, 4}}, + {0, {{1, 2, 8, 12}, 6}}, + {0, {{1, 2, 3, 9, 13}, 8}}, + {0, {{1, 2, 3, 4, 10, 14}, 10}}, + {0, {{1, 7, 11, 15}, 5}}, + {0, {{1, 2, 8, 12, 16}, 7}}, + {0, {{1, 2, 3, 9, 13, 17}, 9}}, + {0, {{1, 2, 3, 4, 10, 14, 18}, 11}}, + {0, {{1, 7, 11, 15, 19}, 6}}, + {0, {{1, 2, 8, 12, 16, 20}, 8}}, + {0, {{1, 2, 3, 9, 13, 17, 21}, 10}}, + {0, {{1, 2, 3, 4, 10, 14, 18, 22}, 12}}, + {1, {{7}, 2}}, + {1, {{2, 8}, 4}}, + {1, {{2, 3, 9}, 6}}, + {1, {{2, 3, 4, 10}, 8}}, + {1, {{7, 11}, 3}}, + {1, {{2, 8, 12}, 5}}, + {1, {{2, 3, 9, 13}, 7}}, + {1, {{2, 3, 4, 10, 14}, 9}}, + {1, {{7, 11, 15}, 4}}, + {1, {{2, 8, 12, 16}, 6}}, + {1, {{2, 3, 9, 13, 17}, 8}}, + {1, {{2, 3, 4, 10, 14, 18}, 10}}, + {1, {{7, 11, 15, 19}, 5}}, + {1, {{2, 8, 12, 16, 20}, 7}}, + {1, {{2, 3, 9, 13, 17, 21}, 9}}, + {1, {{2, 3, 4, 10, 14, 18, 22}, 11}}, + {2, {{7}, 2}}, + {2, {{8}, 2}}, + {2, {{3, 9}, 4}}, + {2, {{3, 4, 10}, 6}}, + {2, {{7, 11}, 3}}, + {2, {{8, 12}, 3}}, + {2, {{3, 9, 13}, 5}}, + {2, {{3, 4, 10, 14}, 7}}, + {2, {{7, 11, 15}, 4}}, + {2, {{8, 12, 16}, 4}}, + {2, {{3, 9, 13, 17}, 6}}, + {2, {{3, 4, 10, 14, 18}, 8}}, + {2, {{7, 11, 15, 19}, 5}}, + {2, {{8, 12, 16, 20}, 5}}, + {2, {{3, 9, 13, 17, 21}, 7}}, + {2, {{3, 4, 10, 14, 18, 22}, 9}}, + {3, {{2, 7}, 4}}, + {3, {{8}, 2}}, + {3, {{9}, 2}}, + {3, {{4, 10}, 4}}, + {3, {{2, 7, 11}, 5}}, + {3, {{8, 12}, 3}}, + {3, {{9, 13}, 3}}, + {3, {{4, 10, 14}, 5}}, + {3, {{2, 7, 11, 15}, 6}}, + {3, {{8, 12, 16}, 4}}, + {3, {{9, 13, 17}, 4}}, + {3, {{4, 10, 14, 18}, 6}}, + {3, {{2, 7, 11, 15, 19}, 7}}, + {3, {{8, 12, 16, 20}, 5}}, + {3, {{9, 13, 17, 21}, 5}}, + {3, {{4, 10, 14, 18, 22}, 7}}, + {4, {{3, 2, 7}, 6}}, + {4, {{3, 8}, 4}}, + {4, {{9}, 2}}, + {4, {{10}, 2}}, + {4, {{3, 2, 7, 11}, 7}}, + {4, {{3, 8, 12}, 5}}, + {4, {{9, 13}, 3}}, + {4, {{10, 14}, 3}}, + {4, {{3, 2, 7, 11, 15}, 8}}, + {4, {{3, 8, 12, 16}, 6}}, + {4, {{9, 13, 17}, 4}}, + {4, {{10, 14, 18}, 4}}, + {4, {{3, 2, 7, 11, 15, 19}, 9}}, + {4, {{3, 8, 12, 16, 20}, 7}}, + {4, {{9, 13, 17, 21}, 5}}, + {4, {{10, 14, 18, 22}, 5}}, + {5, {{4, 3, 2, 7}, 8}}, + {5, {{4, 3, 8}, 6}}, + {5, {{4, 9}, 4}}, + {5, {{10}, 2}}, + {5, {{4, 3, 2, 7, 11}, 9}}, + {5, {{4, 3, 8, 12}, 7}}, + {5, {{4, 9, 13}, 5}}, + {5, {{10, 14}, 3}}, + {5, {{4, 3, 2, 7, 11, 15}, 10}}, + {5, {{4, 3, 8, 12, 16}, 8}}, + {5, {{4, 9, 13, 17}, 6}}, + {5, {{10, 14, 18}, 4}}, + {5, {{4, 3, 2, 7, 11, 15, 19}, 11}}, + {5, {{4, 3, 8, 12, 16, 20}, 9}}, + {5, {{4, 9, 13, 17, 21}, 7}}, + {5, {{10, 14, 18, 22}, 5}}, + {6, {{5, 4, 3, 2, 7}, 9}}, + {6, {{5, 4, 3, 8}, 7}}, + {6, {{5, 4, 9}, 5}}, + {6, {{5, 10}, 3}}, + {6, {{5, 4, 3, 2, 7, 11}, 10}}, + {6, {{5, 4, 3, 8, 12}, 8}}, + {6, {{5, 4, 9, 13}, 6}}, + {6, {{5, 10, 14}, 4}}, + {6, {{5, 4, 3, 2, 7, 11, 15}, 11}}, + {6, {{5, 4, 3, 8, 12, 16}, 9}}, + {6, {{5, 4, 9, 13, 17}, 7}}, + {6, {{5, 10, 14, 18}, 5}}, + {6, {{5, 4, 3, 2, 7, 11, 15, 19}, 12}}, + {6, {{5, 4, 3, 8, 12, 16, 20}, 10}}, + {6, {{5, 4, 9, 13, 17, 21}, 8}}, + {6, {{5, 10, 14, 18, 22}, 6}}, + + {7, {{1, 0}, 3}}, + {7, {{1}, 2}}, + {7, {{2}, 2}}, + {7, {{2, 3}, 4}}, + {7, {{2, 3, 4}, 6}}, + {7, {{2, 3, 4, 5}, 8}}, + {7, {{2, 3, 4, 5, 6}, 9}}, + {8, {{2, 1, 0}, 5}}, + {8, {{2, 1}, 4}}, + {8, {{2}, 2}}, + {8, {{3}, 2}}, + {8, {{3, 4}, 4}}, + {8, {{3, 4, 5}, 6}}, + {8, {{3, 4, 5, 6}, 7}}, + {9, {{3, 2, 1, 0}, 7}}, + {9, {{3, 2, 1}, 6}}, + {9, {{3, 2}, 4}}, + {9, {{3}, 2}}, + {9, {{4}, 2}}, + {9, {{4, 5}, 4}}, + {9, {{4, 5, 6}, 5}}, + {10, {{4, 3, 2, 1, 0}, 9}}, + {10, {{4, 3, 2, 1}, 8}}, + {10, {{4, 3, 2}, 6}}, + {10, {{4, 3}, 4}}, + {10, {{4}, 2}}, + {10, {{5}, 2}}, + {10, {{5, 6}, 3}}, + {11, {{7, 1, 0}, 4}}, + {11, {{7, 1}, 3}}, + {11, {{7, 2}, 3}}, + {11, {{7, 2, 3}, 5}}, + {11, {{7, 2, 3, 4}, 7}}, + {11, {{7, 2, 3, 4, 5}, 9}}, + {11, {{7, 2, 3, 4, 5, 6}, 10}}, + {12, {{8, 2, 1, 0}, 6}}, + {12, {{8, 2, 1}, 5}}, + {12, {{8, 2}, 3}}, + {12, {{8, 3}, 3}}, + {12, {{8, 3, 4}, 5}}, + {12, {{8, 3, 4, 5}, 7}}, + {12, {{8, 3, 4, 5, 6}, 8}}, + {13, {{9, 3, 2, 1, 0}, 8}}, + {13, {{9, 3, 2, 1}, 7}}, + {13, {{9, 3, 2}, 5}}, + {13, {{9, 3}, 3}}, + {13, {{9, 4}, 3}}, + {13, {{9, 4, 5}, 5}}, + {13, {{9, 4, 5, 6}, 7}}, + {14, {{10, 4, 3, 2, 1, 0}, 10}}, + {14, {{10, 4, 3, 2, 1}, 9}}, + {14, {{10, 4, 3, 2}, 7}}, + {14, {{10, 4, 3}, 5}}, + {14, {{10, 4}, 3}}, + {14, {{10, 5}, 3}}, + {14, {{10, 5, 6}, 4}}, + {15, {{11, 7, 1, 0}, 5}}, + {15, {{11, 7, 1}, 4}}, + {15, {{11, 7, 2}, 4}}, + {15, {{11, 7, 2, 3}, 6}}, + {15, {{11, 7, 2, 3, 4}, 8}}, + {15, {{11, 7, 2, 3, 4, 5}, 10}}, + {15, {{11, 7, 2, 3, 4, 5, 6}, 11}}, + {16, {{12, 8, 2, 1, 0}, 7}}, + {16, {{12, 8, 2, 1}, 6}}, + {16, {{12, 8, 2}, 4}}, + {16, {{12, 8, 3}, 4}}, + {16, {{12, 8, 3, 4}, 6}}, + {16, {{12, 8, 3, 4, 5}, 8}}, + {16, {{12, 8, 3, 4, 5, 6}, 9}}, + {17, {{13, 9, 3, 2, 1, 0}, 9}}, + {17, {{13, 9, 3, 2, 1}, 8}}, + {17, {{13, 9, 3, 2}, 6}}, + {17, {{13, 9, 3}, 4}}, + {17, {{13, 9, 4}, 4}}, + {17, {{13, 9, 4, 5}, 6}}, + {17, {{13, 9, 4, 5, 6}, 8}}, + {18, {{14, 10, 4, 3, 2, 1, 0}, 11}}, + {18, {{14, 10, 4, 3, 2, 1}, 10}}, + {18, {{14, 10, 4, 3, 2}, 8}}, + {18, {{14, 10, 4, 3}, 7}}, + {18, {{14, 10, 4}, 4}}, + {18, {{14, 10, 5}, 4}}, + {18, {{14, 10, 5, 6}, 5}}, + {19, {{15, 11, 7, 1, 0}, 6}}, + {19, {{15, 11, 7, 1}, 5}}, + {19, {{15, 11, 7, 2}, 5}}, + {19, {{15, 11, 7, 2, 3}, 7}}, + {19, {{15, 11, 7, 2, 3, 4}, 9}}, + {19, {{15, 11, 7, 2, 3, 4, 5}, 11}}, + {19, {{15, 11, 7, 2, 3, 4, 5, 6}, 12}}, + {20, {{16, 12, 8, 2, 1, 0}, 8}}, + {20, {{16, 12, 8, 2, 1}, 7}}, + {20, {{16, 12, 8, 2}, 5}}, + {20, {{16, 12, 8, 3}, 5}}, + {20, {{16, 12, 8, 3, 4}, 7}}, + {20, {{16, 12, 8, 3, 4, 5}, 9}}, + {20, {{16, 12, 8, 3, 4, 5, 6}, 10}}, + {21, {{17, 13, 9, 3, 2, 1, 0}, 10}}, + {21, {{17, 13, 9, 3, 2, 1}, 9}}, + {21, {{17, 13, 9, 3, 2}, 7}}, + {21, {{17, 13, 9, 3}, 5}}, + {21, {{17, 13, 9, 4}, 5}}, + {21, {{17, 13, 9, 4, 5}, 7}}, + {21, {{17, 13, 9, 4, 5, 6}, 9}}, + {22, {{18, 14, 10, 4, 3, 2, 1, 0}, 12}}, + {22, {{18, 14, 10, 4, 3, 2, 1}, 11}}, + {22, {{18, 14, 10, 4, 3, 2}, 9}}, + {22, {{18, 14, 10, 4, 3}, 8}}, + {22, {{18, 14, 10, 4}, 5}}, + {22, {{18, 14, 10, 5}, 5}}, + {22, {{18, 14, 10, 5, 6}, 6}}, +}; std::map multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}}; @@ -76,93 +288,31 @@ struct State return nodes_[from] != finished_[from]; } if (from > 14 && from < 19) { - if (to < 15) { - // Second bottom row - only move up if we're not meant to be here or the one below isn't. - return nodes_[from] != finished_[from] || - (nodes_[from + 4] != '.' && nodes_[from + 4] != finished_[from + 4]); - } - - // Moving down - only do it if we're of the right type. - return nodes_[from] == finished_[to]; + return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from]; } if (from > 10 && from < 15) { - // Second top row. - if (to < 11) { - return nodes_[from] != finished_[from] || - (nodes_[from + 4] != '.' && nodes_[from + 4] != finished_[from + 4]) || - (nodes_[from + 8] != '.' && nodes_[from + 8] != finished_[from + 8]); - } - - // Moving down - only do it if we're of the right type. - return nodes_[from] == finished_[to]; + return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from] || + nodes_[from + 8] != finished_[from + 8]; } if (from > 6 && from < 11) { - if (to > 10) { - // Only move into bottom position if we're moving the correct piece. - return nodes_[from] == finished_[to]; - } - // Moving to top row - if (to == 0 && nodes_[1] != '.') { - return false; - } - if (to < 2 && from > 7 && nodes_[2] != '.') { - return false; - } - if (to < 3 && from > 8 && nodes_[3] != '.') { - return false; - } - if (to < 4 && from > 9 && nodes_[4] != '.') { - return false; - } - - if (to == 6 && nodes_[5] != '.') { - return false; - } - if (to > 4 && from < 10 && nodes_[4] != '.') { - return false; - } - if (to > 3 && from < 9 && nodes_[3] != '.') { - return false; - } - if (to > 2 && from < 8 && nodes_[2] != '.') { - return false; - } - - return true; + return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from] || + nodes_[from + 8] != finished_[from] || nodes_[from + 12] != finished_[from]; } if (from < 7) { - // Can only move down if we're the right type. + // Can only move down if we're the right type and anything already in the node is the right + // type. if (nodes_[from] != finished_[to]) { return false; } - - // Now encode the rules about moving along the top. - if (from == 0 && nodes_[1] != '.') { - return false; + while (to > 10) { + to -= 4; } - if (from < 2 && to > 7 && nodes_[2] != '.') { - return false; + while (to < 22) { + if (nodes_[to] != '.' && nodes_[to] != finished_[to]) { + return false; + } + to += 4; } - if (from < 3 && to > 8 && nodes_[3] != '.') { - return false; - } - if (from < 4 && to > 9 && nodes_[4] != '.') { - return false; - } - - if (from == 6 && nodes_[5] != '.') { - return false; - } - if (from > 4 && to < 10 && nodes_[4] != '.') { - return false; - } - if (from > 3 && to < 9 && nodes_[3] != '.') { - return false; - } - if (from > 2 && to < 8 && nodes_[2] != '.') { - return false; - } - return true; } abort(); @@ -191,7 +341,6 @@ 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" @@ -220,9 +369,18 @@ struct StateTranstitionManager auto [it_begin, it_end] = valid_moves.equal_range(i); for (auto move_it{it_begin}; move_it != it_end; ++move_it) { State next_state(state); - UInt cost_delta = move_it->second.second * multipliers[state.node(i)]; - if (next_state.move(i, move_it->second.first, cost_delta)) { - inserter(next_state, cost_delta); + bool cont = true; + for (auto pos_it : move_it->second.first) { + if (state.node(pos_it) != '.') { + cont = false; + break; + } + } + if (cont) { + UInt cost_delta = move_it->second.second * multipliers[state.node(i)]; + if (next_state.move(i, move_it->second.first.back(), cost_delta)) { + inserter(next_state, cost_delta); + } } } } @@ -231,15 +389,6 @@ struct StateTranstitionManager auto main() -> int { - std::cout << "digraph { \n"; - for (auto move_it : valid_moves) { - if (move_it.first < move_it.second.first) { - continue; - } - std::cout << (int)move_it.first << " -> " << (int)move_it.second.first << " [label=\"" - << move_it.second.second << "\" ];\n"; - } - std::cout << "};\n"; std::regex line2_re{R"(#(.)(.)\.(.)\.(.)\.(.)\.(.)(.)#)"}; std::regex line3_re{"###(.)#(.)#(.)#(.)###"}; std::regex line4_re{"#(.)#(.)#(.)#(.)#"};