From 4e6626595e1497dfa47f3f39874fcc15658133e7 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 29 Dec 2024 16:37:22 +0800 Subject: [PATCH] feat: add demo of `S2Mover` --- src/core/CMakeLists.txt | 1 + src/core/main.cc | 59 +++- src/core/mover/internal/s2_mover.cc | 403 ++++++++++++++++++++++++++++ src/core/mover/mover.h | 2 + src/core/mover/s2_mover.h | 24 ++ 5 files changed, 480 insertions(+), 9 deletions(-) create mode 100644 src/core/mover/internal/s2_mover.cc create mode 100644 src/core/mover/s2_mover.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aea6299..a5d4ae2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -86,6 +86,7 @@ set(KLSK_CORE_SRC # short_code/internal/serialize.cc mover/internal/mover.cc + mover/internal/s2_mover.cc group/internal/group_union.cc group/internal/group.cc diff --git a/src/core/main.cc b/src/core/main.cc index 318a1f2..439e329 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -18,6 +18,7 @@ using klotski::Analyse; +using klotski::mover::S2Mover; using klotski::mover::MaskMover; using klotski::fast_cal::FastCal; @@ -33,6 +34,7 @@ using klotski::group::Group; using klotski::group::GroupCases; using klotski::group::GroupUnion; +using klotski::group::BLOCK_NUM; using klotski::group::TYPE_ID_LIMIT; using klotski::cases::ALL_CASES_NUM_; using klotski::codec::SHORT_CODE_LIMIT; @@ -48,17 +50,56 @@ int main() { const auto start = std::chrono::system_clock::now(); - // TODO: maybe we can support `std::format` + // constexpr std::array s2_type_a_up = {"1a9bf0c", "1a99c3", "1abaf0c", "1aaef0c", "1aaac3", "9aaac3"}; + // constexpr std::array s2_type_a_down = {"dc3be68", "dc399a", "dc3bae8", "dc3aee8", "dc3aaa", "5c3aaa"}; + // constexpr std::array s2_type_a_left = {"1a9bfc", "1a9bd"}; + // constexpr std::array s2_type_a_right = {"1a9bc3c", "1a9bc1"}; + + // const auto code = CommonCode::from_string(s2_type_a_up[5]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s2_type_a_down[5]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s2_type_a_left[1]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s2_type_a_right[1]).value().to_raw_code(); + + // constexpr std::array s2_type_b_up = {"5fef84d", "5fea134"}; + // constexpr std::array s2_type_b_down = {"9346fbf", "9346afc"}; + // constexpr std::array s2_type_b_left = {"6bfaf1c", "6bfae1", "6bfaf34", "6bfa47", "6bfa4d", "dbf993"}; + // constexpr std::array s2_type_b_right = {"4fea3cd", "4fea2c4", "4fea3c7", "4fea134", "4fea11c", "dfe660c"}; + + // const auto code = CommonCode::from_string(s2_type_b_up[1]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s2_type_b_down[1]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s2_type_b_left[5]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s2_type_b_right[5]).value().to_raw_code(); + + // constexpr std::array s1_up = {"5f2f87d", "5f2a1f4"}; + // constexpr std::array s1_down = {"9f46fbc", "9f46af"}; + // constexpr std::array s1_left = {"1a9bcf", "1a9bc4"}; + // constexpr std::array s1_right = {"1a9bcf", "1a9bc4"}; + // const auto code = CommonCode::from_string(s1_up[1]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s1_down[1]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s1_left[1]).value().to_raw_code(); + // const auto code = CommonCode::from_string(s1_right[1]).value().to_raw_code(); + + auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); + S2Mover mover([](uint64_t code) { + std::cout << RawCode::unsafe_create(code) << std::endl; + if (!RawCode::check(code)) { + std::cout << "error" << std::endl; + std::abort(); + } + }); + mover.next_cases(code.unwrap()); - const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); - const auto solve_1 = CommonCode::unsafe_create(0xDAAF4CC00).to_raw_code(); - const auto solve_2 = CommonCode::unsafe_create(0xDAA7F3000).to_raw_code(); + // TODO: maybe we can support `std::format` - Analyse analyse {code}; - analyse.build(); - const auto backtrack = analyse.backtrack({solve_1, solve_2}); - std::cout << backtrack.size() << std::endl; - std::cout << backtrack[0].size() << ", " << backtrack[81].size() << std::endl; + // const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); + // const auto solve_1 = CommonCode::unsafe_create(0xDAAF4CC00).to_raw_code(); + // const auto solve_2 = CommonCode::unsafe_create(0xDAA7F3000).to_raw_code(); + + // Analyse analyse {code}; + // analyse.build(); + // const auto backtrack = analyse.backtrack({solve_1, solve_2}); + // std::cout << backtrack.size() << std::endl; + // std::cout << backtrack[0].size() << ", " << backtrack[81].size() << std::endl; // const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); // const auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code(); diff --git a/src/core/mover/internal/s2_mover.cc b/src/core/mover/internal/s2_mover.cc new file mode 100644 index 0000000..4045455 --- /dev/null +++ b/src/core/mover/internal/s2_mover.cc @@ -0,0 +1,403 @@ +#include + +#include "mover/s2_mover.h" +#include "raw_code/raw_code.h" + +using klotski::mover::S2Mover; +using klotski::codec::RawCode; + +#define APPLY_MASK(code, addr, mask) \ + (((code) >> ((addr) * 3)) & (uint64_t)(mask)) + +#define UNSET_1x1(code, addr) \ + ((code) & ~((uint64_t)0b111 << ((addr) * 3))) + +#define SET_1x1(code, addr) \ + ((code) | ((uint64_t)0b011 << ((addr) * 3))) + +#define UNSET_1x2(code, addr) \ + ((code) & ~((uint64_t)0b111'111 << ((addr) * 3))) + +#define SET_1x2(code, addr) \ + ((code) | ((uint64_t)0b111'001 << ((addr) * 3))) + +#define UNSET_2x1(code, addr) \ + ((code) & ~((uint64_t)0b111'000'000'000'111 << ((addr) * 3))) + +#define SET_2x1(code, addr) \ + ((code) | ((uint64_t)0b111'000'000'000'010 << ((addr) * 3))) + +#define UNSET_2x2(code, addr) \ + ((code) & ~((uint64_t)0b111'111'000'000'111'111 << ((addr) * 3))) + +#define SET_2x2(code, addr) \ + ((code) | ((uint64_t)0b111'111'000'000'111'100 << ((addr) * 3))) + +void S2Mover::two_space_a(uint64_t code, int offset) const { + // TODO: only apply once (maybe using goto or do-while) + + // ---------------- case up ---------------- + + if (offset >= 4) { + /// 1x1 & 1x1 + if (APPLY_MASK(code, offset - 4, 0b111'111) == 0b011'011) { + auto tmp_1 = UNSET_1x1(code, offset - 4); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 1)); + auto tmp_2 = UNSET_1x1(code, offset - 3); + release_(SET_1x1(tmp_2, offset + 1)); + release_(SET_1x1(tmp_2, offset)); + } + + /// 1x2 + if (APPLY_MASK(code, offset - 4, 0b111'111) == 0b111'001) { + release_(SET_1x2(UNSET_1x2(code, offset - 4), offset)); + } + } + if (offset >= 8) { + /// 1x1 & 2x1 + if (APPLY_MASK(code, offset - 8, 0b111'111'000'000'111'000) == 0b111'011'000'000'010'000) { + auto tmp_1 = UNSET_1x1(code, offset - 4); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 1)); + release_(SET_2x1(UNSET_2x1(code, offset - 7), offset - 3)); + } + + /// 2x1 & 1x1 + if (APPLY_MASK(code, offset - 8, 0b111'111'000'000'000'111) == 0b011'111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset - 8), offset - 4)); + auto tmp_1 = UNSET_1x1(code, offset - 3); + release_(SET_1x1(tmp_1, offset + 1)); + release_(SET_1x1(tmp_1, offset)); + } + + /// 2x1 & 2x1 + if (APPLY_MASK(code, offset - 8, 0b111'111'000'000'111'111) == 0b111'111'000'000'010'010) { + release_(SET_2x1(UNSET_2x1(code, offset - 8), offset - 4)); + release_(SET_2x1(UNSET_2x1(code, offset - 7), offset - 3)); + } + + /// 2x2 + if (APPLY_MASK(code, offset - 8, 0b111'111'000'000'111'111) == 0b111'111'000'000'111'100) { + release_(SET_2x2(UNSET_2x2(code, offset - 8), offset - 4)); + } + } + + // ---------------- case down ---------------- + + if (offset < 16) { + /// 1x1 & 1x1 + if (APPLY_MASK(code, offset + 4, 0b111'111) == 0b011'011) { + auto tmp_1 = UNSET_1x1(code, offset + 4); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 1)); + auto tmp_2 = UNSET_1x1(code, offset + 5); + release_(SET_1x1(tmp_2, offset + 1)); + release_(SET_1x1(tmp_2, offset)); + } + + /// 1x2 + if (APPLY_MASK(code, offset + 4, 0b111'111) == 0b111'001) { + release_(SET_1x2(UNSET_1x2(code, offset + 4), offset)); + } + } + if (offset < 12) { + /// 1x1 & 2x1 + if (APPLY_MASK(code, offset + 4, 0b111'000'000'000'111'111) == 0b111'000'000'000'010'011) { + auto tmp_1 = UNSET_1x1(code, offset + 4); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 1)); + release_(SET_2x1(UNSET_2x1(code, offset + 5), offset + 1)); + } + + /// 2x1 & 1x1 + if (APPLY_MASK(code, offset + 4, 0b000'111'000'000'111'111) == 0b000'111'000'000'011'010) { + release_(SET_2x1(UNSET_2x1(code, offset + 4), offset)); + auto tmp_1 = UNSET_1x1(code, offset + 5); + release_(SET_1x1(tmp_1, offset + 1)); + release_(SET_1x1(tmp_1, offset)); + } + + /// 2x1 & 2x1 + if (APPLY_MASK(code, offset + 4, 0b111'111'000'000'111'111) == 0b111'111'000'000'010'010) { + release_(SET_2x1(UNSET_2x1(code, offset + 4), offset)); + release_(SET_2x1(UNSET_2x1(code, offset + 5), offset + 1)); + } + + /// 2x2 + if (APPLY_MASK(code, offset + 4, 0b111'111'000'000'111'111) == 0b111'111'000'000'111'100) { + release_(SET_2x2(UNSET_2x2(code, offset + 4), offset)); + } + } + + // ---------------- case left ---------------- + + if ((offset % 4) != 0) { + /// 1x1 + if (APPLY_MASK(code, offset - 1, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset - 1), offset)); + release_(SET_1x1(UNSET_1x1(code, offset - 1), offset + 1)); + } + } + if ((offset % 4) == 2) { + /// 1x2 + if (APPLY_MASK(code, offset - 2, 0b111'111) == 0b111'001) { + release_(SET_1x2(UNSET_1x2(code, offset - 2), offset - 1)); + release_(SET_1x2(UNSET_1x2(code, offset - 2), offset)); + } + } + + // ---------------- case right ---------------- + + if ((offset % 4) != 2) { + /// 1x1 + if (APPLY_MASK(code, offset + 2, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset + 2), offset + 1)); + release_(SET_1x1(UNSET_1x1(code, offset + 2), offset)); + } + } + if ((offset % 4) == 0) { + /// 1x2 + if (APPLY_MASK(code, offset + 2, 0b111'111) == 0b111'001) { + release_(SET_1x2(UNSET_1x2(code, offset + 2), offset + 1)); + release_(SET_1x2(UNSET_1x2(code, offset + 2), offset)); + } + } +} + +void S2Mover::two_space_b(uint64_t code, int offset) const { + // ---------------- case up ---------------- + + if (offset >= 4) { + /// 1x1 + if (APPLY_MASK(code, offset - 4, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset - 4), offset)); + release_(SET_1x1(UNSET_1x1(code, offset - 4), offset + 4)); + } + } + if (offset >= 8) { + /// 2x1 + if (APPLY_MASK(code, offset - 8, 0b111'000'000'000'111) == 0b111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset - 8), offset - 4)); + release_(SET_2x1(UNSET_2x1(code, offset - 8), offset)); + } + } + + // ---------------- case down ---------------- + + if (offset < 16) { + /// 1x1 + if (APPLY_MASK(code, offset + 8, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset + 8), offset + 4)); + release_(SET_1x1(UNSET_1x1(code, offset + 8), offset)); + } + } + if (offset < 12) { + /// 2x1 + if (APPLY_MASK(code, offset + 8, 0b111'000'000'000'111) == 0b111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset + 8), offset + 4)); + release_(SET_2x1(UNSET_2x1(code, offset + 8), offset)); + } + } + + // ---------------- case left ---------------- + + if ((offset % 4) != 0) { + /// 1x1 & 1x1 + if (APPLY_MASK(code, offset - 1, 0b111'000'000'000'111) == 0b011'000'000'000'011) { + auto tmp_1 = UNSET_1x1(code, offset - 1); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 4)); + auto tmp_2 = UNSET_1x1(code, offset + 3); + release_(SET_1x1(tmp_2, offset + 4)); + release_(SET_1x1(tmp_2, offset)); + } + + /// 2x1 + if (APPLY_MASK(code, offset - 1, 0b111'000'000'000'111) == 0b111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset - 1), offset)); + } + } + if ((offset % 4) >= 2) { + /// 1x1 & 1x2 + if (APPLY_MASK(code, offset - 2, 0b111'111'000'000'111'000) == 0b111'001'000'000'011'000) { + auto tmp_1 = UNSET_1x1(code, offset - 1); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 4)); + release_(SET_1x2(UNSET_1x2(code, offset + 2), offset + 3)); + } + + /// 1x2 & 1x1 + if (APPLY_MASK(code, offset - 2, 0b111'000'000'000'111'111) == 0b011'000'000'000'111'001) { + release_(SET_1x2(UNSET_1x2(code, offset - 2), offset - 1)); + auto tmp_1 = UNSET_1x1(code, offset + 3); + release_(SET_1x1(tmp_1, offset + 4)); + release_(SET_1x1(tmp_1, offset)); + } + + /// 1x2 & 1x2 + if (APPLY_MASK(code, offset - 2, 0b111'111'000'000'111'111) == 0b111'001'000'000'111'001) { + release_(SET_1x2(UNSET_1x2(code, offset - 2), offset - 1)); + release_(SET_1x2(UNSET_1x2(code, offset + 2), offset + 3)); + } + + /// 2x2 + if (APPLY_MASK(code, offset - 2, 0b111'111'000'000'111'111) == 0b111'111'000'000'111'100) { + release_(SET_2x2(UNSET_2x2(code, offset - 2), offset - 1)); + } + } + + // ---------------- case right ---------------- + + if ((offset % 4) != 3) { + /// 1x1 & 1x1 + if (APPLY_MASK(code, offset + 1, 0b111'000'000'000'111) == 0b011'000'000'000'011) { + auto tmp_1 = UNSET_1x1(code, offset + 1); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 4)); + auto tmp_2 = UNSET_1x1(code, offset + 5); + release_(SET_1x1(tmp_2, offset + 4)); + release_(SET_1x1(tmp_2, offset)); + } + + /// 2x1 + if (APPLY_MASK(code, offset + 1, 0b111'000'000'000'111) == 0b111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset + 1), offset)); + } + } + if ((offset % 4) <= 1) { + /// 1x1 & 1x2 + if (APPLY_MASK(code, offset + 1, 0b111'111'000'000'000'111) == 0b111'001'000'000'000'011) { + auto tmp_1 = UNSET_1x1(code, offset + 1); + release_(SET_1x1(tmp_1, offset)); + release_(SET_1x1(tmp_1, offset + 4)); + release_(SET_1x2(UNSET_1x2(code, offset + 5), offset + 4)); + } + + /// 1x2 & 1x1 + if (APPLY_MASK(code, offset + 1, 0b000'111'000'000'111'111) == 0b000'011'000'000'111'001) { + release_(SET_1x2(UNSET_1x2(code, offset + 1), offset)); + auto tmp_1 = UNSET_1x1(code, offset + 5); + release_(SET_1x1(tmp_1, offset + 4)); + release_(SET_1x1(tmp_1, offset)); + } + + /// 1x2 & 1x2 + if (APPLY_MASK(code, offset + 1, 0b111'111'000'000'111'111) == 0b111'001'000'000'111'001) { + release_(SET_1x2(UNSET_1x2(code, offset + 1), offset)); + release_(SET_1x2(UNSET_1x2(code, offset + 5), offset + 4)); + } + + /// 2x2 + if (APPLY_MASK(code, offset + 1, 0b111'111'000'000'111'111) == 0b111'111'000'000'111'100) { + release_(SET_2x2(UNSET_2x2(code, offset + 1), offset)); + } + } +} + +void S2Mover::one_space(uint64_t code, int offset) const { + // ---------------- case up ---------------- + + if (offset >= 4) { + /// 1x1 + if (APPLY_MASK(code, offset - 4, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset - 4), offset)); + } + } + if (offset >= 8) { + /// 2x1 + if (APPLY_MASK(code, offset - 8, 0b111'000'000'000'111) == 0b111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset - 8), offset - 4)); + } + } + + // ---------------- case down ---------------- + + if (offset < 16) { + /// 1x1 + if (APPLY_MASK(code, offset + 4, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset + 4), offset)); + } + } + if (offset < 12) { + /// 2x1 + if (APPLY_MASK(code, offset + 4, 0b111'000'000'000'111) == 0b111'000'000'000'010) { + release_(SET_2x1(UNSET_2x1(code, offset + 4), offset)); + } + } + + // ---------------- case left ---------------- + + if ((offset % 4) != 0) { + /// 1x1 + if (APPLY_MASK(code, offset - 1, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset - 1), offset)); + } + } + if ((offset % 4) >= 2) { + /// 1x2 + if (APPLY_MASK(code, offset - 2, 0b111'111) == 0b111'001) { + release_(SET_1x2(UNSET_1x2(code, offset - 2), offset - 1)); + } + } + + // ---------------- case right ---------------- + + if ((offset % 4) != 3) { + /// 1x1 + if (APPLY_MASK(code, offset + 1, 0b111) == 0b011) { + release_(SET_1x1(UNSET_1x1(code, offset + 1), offset)); + } + } + if ((offset % 4) <= 1) { + /// 1x2 + if (APPLY_MASK(code, offset + 1, 0b111'111) == 0b111'001) { + release_(SET_1x2(UNSET_1x2(code, offset + 1), offset)); + } + } +} + +void S2Mover::next_cases(uint64_t code) { + // std::cout << RawCode::unsafe_create(code) << std::endl; + + // constexpr int space_1 = 17, space_2 = 18; + // constexpr int space_1 = 1, space_2 = 2; + // constexpr int space_1 = 18, space_2 = 19; + // constexpr int space_1 = 16, space_2 = 17; + // two_space_a(code, space_1); + + // constexpr int space_1 = 12, space_2 = 16; + // constexpr int space_1 = 0, space_2 = 4; + // constexpr int space_1 = 15, space_2 = 19; + // constexpr int space_1 = 12, space_2 = 16; + // two_space_b(code, space_1); + + // constexpr int space = 12; + // constexpr int space = 4; + // constexpr int space = 19; + // constexpr int space = 16; + // one_space(code, space); + + int space_1 = -1; + int space_2 = -1; + for (int addr = 0; addr < 20; ++addr) { + if (((code >> (addr * 3)) & 0b111) == 0) { + if (space_1 == -1) { + space_1 = addr; + continue; + } + space_2 = addr; + } + } + // std::cout << space_1 << std::endl; + // std::cout << space_2 << std::endl; + + if (space_1 + 1 == space_2 && space_1 % 4 != 3) { + two_space_a(code, space_1); + } else if (space_1 + 4 == space_2) { + two_space_b(code, space_1); + } else { + one_space(code, space_1); + one_space(code, space_2); + } +} diff --git a/src/core/mover/mover.h b/src/core/mover/mover.h index 6badfd8..9d8d078 100644 --- a/src/core/mover/mover.h +++ b/src/core/mover/mover.h @@ -98,3 +98,5 @@ private: }; } // namespace klotski::mover + +#include "s2_mover.h" diff --git a/src/core/mover/s2_mover.h b/src/core/mover/s2_mover.h new file mode 100644 index 0000000..005f770 --- /dev/null +++ b/src/core/mover/s2_mover.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace klotski::mover { + +class S2Mover { +public: + using release_t = std::function; + + explicit S2Mover(release_t release_func) : release_(std::move(release_func)) {} + + void next_cases(uint64_t code); + +private: + release_t release_; + + void two_space_a(uint64_t code, int offset) const; + void two_space_b(uint64_t code, int offset) const; + + void one_space(uint64_t code, int offset) const; +}; + +} // namespace klotski::mover