Completed puzzles for 2021 day 23
This commit is contained in:
@@ -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
|
/** \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.
|
* 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. */
|
/** \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;
|
std::map<Cost, std::unordered_set<Node const*>> costs;
|
||||||
Cost current_cost{initial_cost};
|
Cost current_cost{initial_cost};
|
||||||
Node const* current_node{new Node(initial)};
|
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}});
|
costs.insert({current_cost, {current_node}});
|
||||||
|
|
||||||
/* Helper lambda to clean up after ourselves. */
|
/* 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. */
|
/* 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;
|
cost += current_cost;
|
||||||
auto node_it{nodes.find(&node)};
|
auto node_it{nodes.find(&node)};
|
||||||
/* Skip inserting nodes we've already visited, or that would cost more to visit. */
|
/* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node const* nodep{nullptr};
|
Node const* nodep{nullptr};
|
||||||
if (node_it == nodes.end()) {
|
if (node_it == nodes.end()) {
|
||||||
nodep = new Node(node);
|
nodep = new Node(node);
|
||||||
nodes.insert({nodep, {cost, current_node}});
|
nodes.insert({nodep, cost});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Node has a cheaper cost than we thought: Remove the node from its old cost list */
|
/* Node has a cheaper cost than we thought: Remove the node from its old cost list */
|
||||||
nodep = node_it->first;
|
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());
|
assert(cost_it != costs.end());
|
||||||
cost_it->second.erase(nodep);
|
cost_it->second.erase(nodep);
|
||||||
|
|
||||||
/* Now update the cost in the nodes map and use the nodep as the node pointer. */
|
/* Now update the cost in the nodes map and use the nodep as the node pointer. */
|
||||||
node_it->second.first = cost;
|
node_it->second = cost;
|
||||||
node_it->second.second = current_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [cost_it, success] = costs.insert({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();
|
return a + c.second.size();
|
||||||
}) == nodes.size() - iter);
|
}) == nodes.size() - iter);
|
||||||
for (auto& nodep : cost_it->second) {
|
for (auto& nodep : cost_it->second) {
|
||||||
current_node = nodep;
|
|
||||||
if (iter++ % 100'000 == 0) {
|
if (iter++ % 100'000 == 0) {
|
||||||
std::cout << "Iteration: " << iter << " cost " << current_cost
|
std::cout << "Iteration: " << iter << " cost " << current_cost
|
||||||
<< " total number of nodes: " << nodes.size()
|
<< " 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)) {
|
if (transition_manager.is_finished(*nodep)) {
|
||||||
auto result{std::make_pair(*nodep, current_cost)};
|
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);
|
cleanup(nodes);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -32,17 +32,121 @@ using Position = char;
|
|||||||
using UInt = int;
|
using UInt = int;
|
||||||
using Type = char;
|
using Type = char;
|
||||||
|
|
||||||
std::multimap<Position, std::pair<Position, UInt>> valid_moves{
|
std::multimap<Position, std::pair<std::vector<Position>, UInt>> valid_moves{
|
||||||
{0, {7, 3}}, {0, {8, 5}}, {0, {9, 7}}, {0, {10, 9}}, {1, {7, 2}}, {1, {8, 4}}, {1, {9, 6}},
|
{0, {{1, 7}, 3}},
|
||||||
{1, {10, 8}}, {2, {7, 2}}, {2, {8, 2}}, {2, {9, 4}}, {2, {10, 6}}, {3, {7, 4}}, {3, {8, 2}},
|
{0, {{1, 2, 8}, 5}},
|
||||||
{3, {9, 2}}, {3, {10, 4}}, {4, {7, 6}}, {4, {8, 4}}, {4, {9, 2}}, {4, {10, 2}}, {5, {7, 8}},
|
{0, {{1, 2, 3, 9}, 7}},
|
||||||
{5, {8, 6}}, {5, {9, 4}}, {5, {10, 2}}, {6, {7, 9}}, {6, {8, 7}}, {6, {9, 5}}, {6, {10, 3}},
|
{0, {{1, 2, 3, 4, 10}, 9}},
|
||||||
{7, {0, 3}}, {7, {1, 2}}, {7, {2, 2}}, {7, {3, 4}}, {7, {4, 6}}, {7, {5, 8}}, {7, {6, 9}},
|
{0, {{1, 7, 11}, 4}},
|
||||||
{7, {11, 1}}, {8, {0, 5}}, {8, {1, 4}}, {8, {2, 2}}, {8, {3, 2}}, {8, {4, 4}}, {8, {5, 6}},
|
{0, {{1, 2, 8, 12}, 6}},
|
||||||
{8, {6, 7}}, {8, {12, 1}}, {9, {0, 7}}, {9, {1, 6}}, {9, {2, 4}}, {9, {3, 2}}, {9, {4, 2}},
|
{0, {{1, 2, 3, 9, 13}, 8}},
|
||||||
{9, {5, 4}}, {9, {6, 5}}, {9, {13, 1}}, {10, {0, 9}}, {10, {1, 8}}, {10, {2, 6}}, {10, {3, 4}},
|
{0, {{1, 2, 3, 4, 10, 14}, 10}},
|
||||||
{10, {4, 2}}, {10, {5, 2}}, {10, {6, 3}}, {10, {14, 1}}, {11, {7, 1}}, {12, {8, 1}}, {13, {9, 1}},
|
{1, {{7}, 2}},
|
||||||
{14, {10, 1}}};
|
{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<Type, UInt> multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}};
|
std::map<Type, UInt> multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}};
|
||||||
|
|
||||||
@@ -56,18 +160,6 @@ struct State
|
|||||||
|
|
||||||
bool check_move(unsigned from, unsigned to)
|
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] != '.') {
|
if (nodes_[from] == '.' || nodes_[to] != '.') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -76,72 +168,22 @@ struct State
|
|||||||
return nodes_[from] != finished_[from];
|
return nodes_[from] != finished_[from];
|
||||||
}
|
}
|
||||||
if (from > 6 && from < 11) {
|
if (from > 6 && from < 11) {
|
||||||
if (to > 10) {
|
// Only move out of the bottom row if we or the node below us is not meant to be there.
|
||||||
// Only move into bottom position if we're moving the correct piece.
|
return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (from < 7) {
|
if (from < 7) {
|
||||||
// Can only move down if we're the right type.
|
|
||||||
if (nodes_[from] != finished_[to]) {
|
if (nodes_[from] != finished_[to]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
while (to > 10) {
|
||||||
// Now encode the rules about moving along the top.
|
to -= 4;
|
||||||
if (from == 0 && nodes_[1] != '.') {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (from < 2 && to > 7 && nodes_[2] != '.') {
|
while (to < 15) {
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
@@ -196,9 +238,18 @@ struct StateTranstitionManager
|
|||||||
auto [it_begin, it_end] = valid_moves.equal_range(i);
|
auto [it_begin, it_end] = valid_moves.equal_range(i);
|
||||||
for (auto move_it{it_begin}; move_it != it_end; ++move_it) {
|
for (auto move_it{it_begin}; move_it != it_end; ++move_it) {
|
||||||
State next_state(state);
|
State next_state(state);
|
||||||
UInt cost_delta = move_it->second.second * multipliers[state.node(i)];
|
bool cont = true;
|
||||||
if (next_state.move(i, move_it->second.first, cost_delta)) {
|
for (auto pos_it : move_it->second.first) {
|
||||||
inserter(next_state, cost_delta);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,21 +38,233 @@ using Position = char;
|
|||||||
using UInt = int;
|
using UInt = int;
|
||||||
using Type = char;
|
using Type = char;
|
||||||
|
|
||||||
std::multimap<Position, std::pair<Position, UInt>> valid_moves{
|
std::multimap<Position, std::pair<std::vector<Position>, UInt>> valid_moves{
|
||||||
{0, {7, 3}}, {0, {8, 5}}, {0, {9, 7}}, {0, {10, 9}}, {1, {7, 2}}, {1, {8, 4}},
|
{0, {{1, 7}, 3}},
|
||||||
{1, {9, 6}}, {1, {10, 8}}, {2, {7, 2}}, {2, {8, 2}}, {2, {9, 4}}, {2, {10, 6}},
|
{0, {{1, 2, 8}, 5}},
|
||||||
{3, {7, 4}}, {3, {8, 2}}, {3, {9, 2}}, {3, {10, 4}}, {4, {7, 6}}, {4, {8, 4}},
|
{0, {{1, 2, 3, 9}, 7}},
|
||||||
{4, {9, 2}}, {4, {10, 2}}, {5, {7, 8}}, {5, {8, 6}}, {5, {9, 4}}, {5, {10, 2}},
|
{0, {{1, 2, 3, 4, 10}, 9}},
|
||||||
{6, {7, 9}}, {6, {8, 7}}, {6, {9, 5}}, {6, {10, 3}}, {7, {0, 3}}, {7, {1, 2}},
|
{0, {{1, 7, 11}, 4}},
|
||||||
{7, {2, 2}}, {7, {3, 4}}, {7, {4, 6}}, {7, {5, 8}}, {7, {6, 9}}, {7, {11, 1}},
|
{0, {{1, 2, 8, 12}, 6}},
|
||||||
{8, {0, 5}}, {8, {1, 4}}, {8, {2, 2}}, {8, {3, 2}}, {8, {4, 4}}, {8, {5, 6}},
|
{0, {{1, 2, 3, 9, 13}, 8}},
|
||||||
{8, {6, 7}}, {8, {12, 1}}, {9, {0, 7}}, {9, {1, 6}}, {9, {2, 4}}, {9, {3, 2}},
|
{0, {{1, 2, 3, 4, 10, 14}, 10}},
|
||||||
{9, {4, 2}}, {9, {5, 4}}, {9, {6, 5}}, {9, {13, 1}}, {10, {0, 9}}, {10, {1, 8}},
|
{0, {{1, 7, 11, 15}, 5}},
|
||||||
{10, {2, 6}}, {10, {3, 4}}, {10, {4, 2}}, {10, {5, 2}}, {10, {6, 3}}, {10, {14, 1}},
|
{0, {{1, 2, 8, 12, 16}, 7}},
|
||||||
{11, {7, 1}}, {12, {8, 1}}, {13, {9, 1}}, {14, {10, 1}}, {11, {15, 1}}, {12, {16, 1}},
|
{0, {{1, 2, 3, 9, 13, 17}, 9}},
|
||||||
{13, {17, 1}}, {14, {18, 1}}, {15, {11, 1}}, {16, {12, 1}}, {17, {13, 1}}, {18, {14, 1}},
|
{0, {{1, 2, 3, 4, 10, 14, 18}, 11}},
|
||||||
{15, {19, 1}}, {16, {20, 1}}, {17, {21, 1}}, {18, {22, 1}}, {19, {15, 1}}, {20, {16, 1}},
|
{0, {{1, 7, 11, 15, 19}, 6}},
|
||||||
{21, {17, 1}}, {22, {18, 1}}};
|
{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<Type, UInt> multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}};
|
std::map<Type, UInt> multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}};
|
||||||
|
|
||||||
@@ -76,93 +288,31 @@ struct State
|
|||||||
return nodes_[from] != finished_[from];
|
return nodes_[from] != finished_[from];
|
||||||
}
|
}
|
||||||
if (from > 14 && from < 19) {
|
if (from > 14 && from < 19) {
|
||||||
if (to < 15) {
|
return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from];
|
||||||
// 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];
|
|
||||||
}
|
}
|
||||||
if (from > 10 && from < 15) {
|
if (from > 10 && from < 15) {
|
||||||
// Second top row.
|
return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from] ||
|
||||||
if (to < 11) {
|
nodes_[from + 8] != finished_[from + 8];
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
if (from > 6 && from < 11) {
|
if (from > 6 && from < 11) {
|
||||||
if (to > 10) {
|
return nodes_[from] != finished_[from] || nodes_[from + 4] != finished_[from] ||
|
||||||
// Only move into bottom position if we're moving the correct piece.
|
nodes_[from + 8] != finished_[from] || nodes_[from + 12] != finished_[from];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (from < 7) {
|
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]) {
|
if (nodes_[from] != finished_[to]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
while (to > 10) {
|
||||||
// Now encode the rules about moving along the top.
|
to -= 4;
|
||||||
if (from == 0 && nodes_[1] != '.') {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (from < 2 && to > 7 && nodes_[2] != '.') {
|
while (to < 22) {
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
@@ -191,7 +341,6 @@ std::array<Type, State::size_> State::finished_ = {'.', '.', '.', '.', '.', '.',
|
|||||||
'B', 'C', 'D', 'A', 'B', 'C', 'D', 'A',
|
'B', 'C', 'D', 'A', 'B', 'C', 'D', 'A',
|
||||||
'B', 'C', 'D', 'A', 'B', 'C', 'D'};
|
'B', 'C', 'D', 'A', 'B', 'C', 'D'};
|
||||||
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, State const& s)
|
std::ostream& operator<<(std::ostream& os, State const& s)
|
||||||
{
|
{
|
||||||
os << "#############\n"
|
os << "#############\n"
|
||||||
@@ -220,9 +369,18 @@ struct StateTranstitionManager
|
|||||||
auto [it_begin, it_end] = valid_moves.equal_range(i);
|
auto [it_begin, it_end] = valid_moves.equal_range(i);
|
||||||
for (auto move_it{it_begin}; move_it != it_end; ++move_it) {
|
for (auto move_it{it_begin}; move_it != it_end; ++move_it) {
|
||||||
State next_state(state);
|
State next_state(state);
|
||||||
UInt cost_delta = move_it->second.second * multipliers[state.node(i)];
|
bool cont = true;
|
||||||
if (next_state.move(i, move_it->second.first, cost_delta)) {
|
for (auto pos_it : move_it->second.first) {
|
||||||
inserter(next_state, cost_delta);
|
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
|
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 line2_re{R"(#(.)(.)\.(.)\.(.)\.(.)\.(.)(.)#)"};
|
||||||
std::regex line3_re{"###(.)#(.)#(.)#(.)###"};
|
std::regex line3_re{"###(.)#(.)#(.)#(.)###"};
|
||||||
std::regex line4_re{"#(.)#(.)#(.)#(.)#"};
|
std::regex line4_re{"#(.)#(.)#(.)#(.)#"};
|
||||||
|
Reference in New Issue
Block a user