diff --git a/2021/puzzle-23-01.cc b/2021/puzzle-23-01.cc index 07ee368..b21b52a 100644 --- a/2021/puzzle-23-01.cc +++ b/2021/puzzle-23-01.cc @@ -14,27 +14,32 @@ // #l#m#n#o# // ######### // -// a -1- b -2- c -2- d -2- e -2- f -1- g +// 0 -1- 1 -2- 2 -2- 3 -2- 4 -2- 5 -1- 6 // \ / \ / \ / \ / // 2 2 2 2 2 2 2 2 // + + + + -// h i j k +// 7 8 9 10 // | | | | // 1 1 1 1 // | | | | -// l m n o +// 11 12 13 14 +// Actually : {0-6} can go to any of {7-10} at varying cost but there are move restritions. using Position = char; using UInt = int; using Type = char; std::multimap> valid_moves{ - {0, {1, 1}}, {1, {0, 1}}, {1, {2, 2}}, {1, {7, 2}}, {2, {1, 2}}, {2, {3, 2}}, - {2, {7, 2}}, {2, {8, 2}}, {3, {2, 2}}, {3, {4, 2}}, {3, {8, 2}}, {3, {9, 2}}, - {4, {3, 2}}, {4, {5, 2}}, {4, {9, 2}}, {4, {10, 2}}, {5, {4, 2}}, {5, {6, 1}}, - {5, {10, 2}}, {6, {5, 1}}, {7, {1, 2}}, {7, {2, 2}}, {7, {11, 1}}, {8, {2, 2}}, - {8, {3, 2}}, {8, {12, 1}}, {9, {3, 2}}, {9, {4, 2}}, {9, {13, 1}}, {10, {4, 2}}, - {10, {5, 2}}, {10, {14, 1}}, {11, {7, 1}}, {12, {8, 1}}, {13, {9, 1}}, {14, {10, 1}}}; + {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::map multipliers{{'A', 1}, {'B', 10}, {'C', 100}, {'D', 1000}}; @@ -48,6 +53,18 @@ 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; } @@ -60,15 +77,69 @@ struct State // Only move into bottom position if we're moving the correct piece. return nodes_[from] == finished_[to]; } - // Moving to top row - anything allowed. + // 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 (to < 7) { - return true; - } // Can only move down if we're the right type. - return nodes_[from] == finished_[to]; + if (nodes_[from] != finished_[to]) { + return false; + } + + // Now encode the rules about moving along the top. + if (from == 0 && nodes_[1] != '.') { + return false; + } + if (from < 2 && to > 7 && nodes_[2] != '.') { + return false; + } + 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(); }