diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index adabe3f..5b6d672 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -88,7 +88,6 @@ set(KLSK_CORE_SRC mover/internal/mover.cc mover/internal/s2_mover.cc mover/internal/s2_hint_mover.cc - mover/internal/s2_demo.cc group/internal/group_union.cc group/internal/group.cc diff --git a/src/core/mover/internal/s2_demo.cc b/src/core/mover/internal/s2_demo.cc deleted file mode 100644 index 3442091..0000000 --- a/src/core/mover/internal/s2_demo.cc +++ /dev/null @@ -1,339 +0,0 @@ -#include "mover/s2_hint_mover.h" - -#include - -#include "raw_code/raw_code.h" - -using klotski::codec::RawCode; -using klotski::mover::S2HintMoverPro; - -#define ADDR(N) ((N) * 3) - -#define CAPTURE(code, N) (((code) >> ADDR(N)) & 0b111ULL) - -#define MOVE_1x1(code, SRC, DST) \ - ((code) & ~(K_MASK_1x1_ << ADDR(SRC)) | (K_MASK_1x1 << ADDR(DST))) - -#define MOVE_1x2(code, SRC, DST) \ - ((code) & ~(K_MASK_1x2_ << ADDR(SRC)) | (K_MASK_1x2 << ADDR(DST))) - -#define MOVE_2x1(code, SRC, DST) \ - ((code) & ~(K_MASK_2x1_ << ADDR(SRC)) | (K_MASK_2x1 << ADDR(DST))) - -#define MOVE_2x2(code, SRC, DST) \ - ((code) & ~(K_MASK_2x2_ << ADDR(SRC)) | (K_MASK_2x2 << ADDR(DST))) - -#define RELEASE_1x1(code, SRC, DST, SP) \ - release_(MOVE_1x1(code, SRC, DST), ((uint64_t)0b1 << (DST + 32)) | (SP)) - -#define RELEASE_1x2(code, SRC, DST, SP) \ - release_(MOVE_1x2(code, SRC, DST), ((uint64_t)0b11 << (DST + 32)) | (SP)) - -#define RELEASE_2x1(code, SRC, DST, SP) \ - release_(MOVE_2x1(code, SRC, DST), ((uint64_t)0b10001 << (DST + 32)) | (SP)) - -#define RELEASE_2x2(code, SRC, DST, SP) \ - release_(MOVE_2x2(code, SRC, DST), ((uint64_t)0b110011 << (DST + 32)) | (SP)) - -#define MAYBE_UP(hint, N) (((hint) & (1 << ((N) - 4))) == 0) - -#define MAYBE_DOWN(hint, N) (((hint) & (1 << ((N) + 4))) == 0) - -#define MAYBE_LEFT(hint, N) (((hint) & (1 << ((N) - 1))) == 0) - -#define MAYBE_RIGHT(hint, N) (((hint) & (1 << ((N) + 1))) == 0) - -#define MAKE_SP(N) ((uint64_t)1 << (N)) - -template -void S2HintMoverPro::move_single(const uint64_t code, const uint32_t hint, const uint32_t kk) const { - if (N >= 4 && MAYBE_UP(hint, N)) { // case up - if (CAPTURE(code, N - 4) == BLOCK_1x1) { - RELEASE_1x1(code, N - 4, N, MAKE_SP(N - 4) | kk); - } else if (N >= 8 && CAPTURE(code, N - 8) == BLOCK_2x1) { - RELEASE_2x1(code, N - 8, N - 4, MAKE_SP(N - 8) | kk); - } - } - - if (N < 16 && MAYBE_DOWN(hint, N)) { // case down - if (const uint8_t block = CAPTURE(code, N + 4); block == BLOCK_1x1) { - RELEASE_1x1(code, N + 4, N, MAKE_SP(N + 4) | kk); - } else if (N < 12 && block == BLOCK_2x1) { - RELEASE_2x1(code, N + 4, N, MAKE_SP(N + 8) | kk); - } - } - - if (N % 4 >= 1 && MAYBE_LEFT(hint, N)) { // case left - if (CAPTURE(code, N - 1) == BLOCK_1x1) { - RELEASE_1x1(code, N - 1, N, MAKE_SP(N - 1) | kk); - } else if (N % 4 >= 2 && CAPTURE(code, N - 2) == BLOCK_1x2) { - RELEASE_1x2(code, N - 2, N - 1, MAKE_SP(N - 2) | kk); - } - } - - if (N % 4 < 3 && MAYBE_RIGHT(hint, N)) { // case right - if (const uint8_t block = CAPTURE(code, N + 1); block == BLOCK_1x1) { - RELEASE_1x1(code, N + 1, N, MAKE_SP(N + 1) | kk); - } else if (N % 4 < 2 && block == BLOCK_1x2) { - RELEASE_1x2(code, N + 1, N, MAKE_SP(N + 2) | kk); - } - } -} - -template -void S2HintMoverPro::move_double_h(const uint64_t code, const uint32_t hint) const { - do { // case up - if (N >= 4 && MAYBE_UP(hint, N)) { - if (const uint8_t block = CAPTURE(code, N - 4); block == BLOCK_1x1) { // left part - RELEASE_1x1(code, N - 4, N, MAKE_SP(N - 4) | MAKE_SP(N + 1)); - RELEASE_1x1(code, N - 4, N + 1, MAKE_SP(N - 4) | MAKE_SP(N)); - } else if (block == BLOCK_1x2) { - RELEASE_1x2(code, N - 4, N, MAKE_SP(N - 4) | MAKE_SP(N - 3)); - break; - } else if (N >= 8 && block == BLOCK_fill) { - if (const uint8_t block_ = CAPTURE(code, N - 8); block_ == BLOCK_2x2) { - RELEASE_2x2(code, N - 8, N - 4, MAKE_SP(N - 8) | MAKE_SP(N - 7)); - break; - } else if (block_ == BLOCK_2x1) { - RELEASE_2x1(code, N - 8, N - 4, MAKE_SP(N - 8) | MAKE_SP(N + 1)); - } - } - if (!MAYBE_UP(hint, N + 1)) { - break; - } - if (const uint8_t block = CAPTURE(code, N - 3); block == BLOCK_1x1) { // right part - RELEASE_1x1(code, N - 3, N + 1, MAKE_SP(N) | MAKE_SP(N - 3)); - RELEASE_1x1(code, N - 3, N, MAKE_SP(N - 3) | MAKE_SP(N + 1)); - } else if (N >= 8 && block == BLOCK_fill && CAPTURE(code, N - 7) == BLOCK_2x1) { - RELEASE_2x1(code, N - 7, N - 3, MAKE_SP(N) | MAKE_SP(N - 7)); - } - } - } while (false); - - do { // case down - if (N < 16 && MAYBE_DOWN(hint, N)) { - if (const uint8_t block = CAPTURE(code, N + 4); block == BLOCK_1x1) { // left part - RELEASE_1x1(code, N + 4, N, MAKE_SP(N + 4) | MAKE_SP(N + 1)); - RELEASE_1x1(code, N + 4, N + 1, MAKE_SP(N + 4) | MAKE_SP(N)); - } else if (N < 12 && block == BLOCK_2x1) { - RELEASE_2x1(code, N + 4, N, MAKE_SP(N + 8) | MAKE_SP(N + 1)); - } else if (block == BLOCK_1x2) { - RELEASE_1x2(code, N + 4, N, MAKE_SP(N + 4) | MAKE_SP(N + 5)); - break; - } else if (N < 12 && block == BLOCK_2x2) { - RELEASE_2x2(code, N + 4, N, MAKE_SP(N + 8) | MAKE_SP(N + 9)); - break; - } - if (!MAYBE_DOWN(hint, N + 1)) { - break; - } - if (const uint8_t block = CAPTURE(code, N + 5); block == BLOCK_1x1) { // right part - RELEASE_1x1(code, N + 5, N + 1, MAKE_SP(N) | MAKE_SP(N + 5)); - RELEASE_1x1(code, N + 5, N, MAKE_SP(N + 1) | MAKE_SP(N + 5)); - } else if (N < 12 && block == BLOCK_2x1) { - RELEASE_2x1(code, N + 5, N + 1, MAKE_SP(N) | MAKE_SP(N + 9)); - } - } - } while (false); - - if (N % 4 >= 1 && MAYBE_LEFT(hint, N)) { // case left - if (CAPTURE(code, N - 1) == BLOCK_1x1) { - RELEASE_1x1(code, N - 1, N, MAKE_SP(N - 1) | MAKE_SP(N + 1)); - RELEASE_1x1(code, N - 1, N + 1, MAKE_SP(N - 1) | MAKE_SP(N)); - } else if (N % 4 == 2 && CAPTURE(code, N - 2) == BLOCK_1x2) { - RELEASE_1x2(code, N - 2, N - 1, MAKE_SP(N - 2) | MAKE_SP(N + 1)); - RELEASE_1x2(code, N - 2, N, MAKE_SP(N - 2) | MAKE_SP(N - 1)); - } - } - - if (N % 4 < 2 && MAYBE_RIGHT(hint, N + 1)) { // case right - if (const uint8_t block = CAPTURE(code, N + 2); block == BLOCK_1x1) { - RELEASE_1x1(code, N + 2, N + 1, MAKE_SP(N) | MAKE_SP(N + 2)); - RELEASE_1x1(code, N + 2, N, MAKE_SP(N + 1) | MAKE_SP(N + 2)); - } else if (N % 4 == 0 && block == BLOCK_1x2) { - RELEASE_1x2(code, N + 2, N + 1, MAKE_SP(N) | MAKE_SP(N + 3)); - RELEASE_1x2(code, N + 2, N, MAKE_SP(N + 2) | MAKE_SP(N + 3)); - } - } -} - -template -void S2HintMoverPro::move_double_v(const uint64_t code, const uint32_t hint) const { - if (N >= 4 && MAYBE_UP(hint, N)) { // case up - if (CAPTURE(code, N - 4) == BLOCK_1x1) { - RELEASE_1x1(code, N - 4, N, MAKE_SP(N - 4) | MAKE_SP(N + 4)); - RELEASE_1x1(code, N - 4, N + 4, MAKE_SP(N - 4) | MAKE_SP(N)); - } else if (N >= 8 && CAPTURE(code, N - 8) == BLOCK_2x1) { - RELEASE_2x1(code, N - 8, N - 4, MAKE_SP(N - 8) | MAKE_SP(N + 4)); - RELEASE_2x1(code, N - 8, N, MAKE_SP(N - 8) | MAKE_SP(N - 4)); - } - } - - if (N < 12 && MAYBE_DOWN(hint, N + 4)) { // case down - if (CAPTURE(code, N + 8) == BLOCK_1x1) { - RELEASE_1x1(code, N + 8, N + 4, MAKE_SP(N) | MAKE_SP(N + 8)); - RELEASE_1x1(code, N + 8, N, MAKE_SP(N + 4) | MAKE_SP(N + 8)); - } else if (N < 8 && CAPTURE(code, N + 8) == BLOCK_2x1) { - RELEASE_2x1(code, N + 8, N + 4, MAKE_SP(N) | MAKE_SP(N + 12)); - RELEASE_2x1(code, N + 8, N, MAKE_SP(N + 8) | MAKE_SP(N + 12)); - } - } - - do { // case left - if (N % 4 != 0 && MAYBE_LEFT(hint, N)) { - if (const uint8_t block = CAPTURE(code, N - 1); block == BLOCK_1x1) { // up part - RELEASE_1x1(code, N - 1, N, MAKE_SP(N - 1) | MAKE_SP(N + 4)); - RELEASE_1x1(code, N - 1, N + 4, MAKE_SP(N - 1) | MAKE_SP(N)); - } else if (block == BLOCK_2x1) { - RELEASE_2x1(code, N - 1, N, MAKE_SP(N - 1) | MAKE_SP(N + 3)); - break; - } else if (N % 4 >= 2 && block == BLOCK_fill) { - if (const uint8_t block_ = CAPTURE(code, N - 2); block_ == BLOCK_2x2) { - RELEASE_2x2(code, N - 2, N - 1, MAKE_SP(N - 2) | MAKE_SP(N + 2)); - break; - } else if (block_ == BLOCK_1x2) { - RELEASE_1x2(code, N - 2, N - 1, MAKE_SP(N - 2) | MAKE_SP(N + 4)); - } - } - if (!MAYBE_LEFT(hint, N + 4)) { - break; - } - if (const uint8_t block = CAPTURE(code, N + 3); block == BLOCK_1x1) { // down part - RELEASE_1x1(code, N + 3, N + 4, MAKE_SP(N) | MAKE_SP(N + 3)); - RELEASE_1x1(code, N + 3, N, MAKE_SP(N + 3) | MAKE_SP(N + 4)); - } else if (N % 4 >= 2 && block == BLOCK_fill && CAPTURE(code, N + 2) == BLOCK_1x2) { - RELEASE_1x2(code, N + 2, N + 3, MAKE_SP(N) | MAKE_SP(N + 2)); - } - } - } while (false); - - do { // case right - if (N % 4 < 3 && MAYBE_RIGHT(hint, N)) { - if (const uint8_t block = CAPTURE(code, N + 1); block == BLOCK_1x1) { // up part - RELEASE_1x1(code, N + 1, N, MAKE_SP(N + 4) | MAKE_SP(N + 1)); - RELEASE_1x1(code, N + 1, N + 4, MAKE_SP(N) | MAKE_SP(N + 1)); - } else if (N % 4 < 2 && block == BLOCK_1x2) { - RELEASE_1x2(code, N + 1, N, MAKE_SP(N + 2) | MAKE_SP(N + 4)); - } else if (block == BLOCK_2x1) { - RELEASE_2x1(code, N + 1, N, MAKE_SP(N + 1) | MAKE_SP(N + 5)); - break; - } else if (N % 4 < 2 && block == BLOCK_2x2) { - RELEASE_2x2(code, N + 1, N, MAKE_SP(N + 2) | MAKE_SP(N + 6)); - break; - } - if (!MAYBE_RIGHT(hint, N + 4)) { - break; - } - if (const uint8_t block = CAPTURE(code, N + 5); block == BLOCK_1x1) { // down part - RELEASE_1x1(code, N + 5, N + 4, MAKE_SP(N) | MAKE_SP(N + 5)); - RELEASE_1x1(code, N + 5, N, MAKE_SP(N + 4) | MAKE_SP(N + 5)); - } else if (N % 4 < 2 && block == BLOCK_1x2) { - RELEASE_1x2(code, N + 5, N + 4, MAKE_SP(N) | MAKE_SP(N + 6)); - } - } - } while (false); -} - -void S2HintMoverPro::move_double_h(const uint64_t code, uint32_t hint, const int offset) const { - switch (offset) { - case 0: move_double_h<0>(code, hint); break; - case 1: move_double_h<1>(code, hint); break; - case 2: move_double_h<2>(code, hint); break; - case 4: move_double_h<4>(code, hint); break; - case 5: move_double_h<5>(code, hint); break; - case 6: move_double_h<6>(code, hint); break; - case 8: move_double_h<8>(code, hint); break; - case 9: move_double_h<9>(code, hint); break; - case 10: move_double_h<10>(code, hint); break; - case 12: move_double_h<12>(code, hint); break; - case 13: move_double_h<13>(code, hint); break; - case 14: move_double_h<14>(code, hint); break; - case 16: move_double_h<16>(code, hint); break; - case 17: move_double_h<17>(code, hint); break; - case 18: move_double_h<18>(code, hint); break; - default: std::unreachable(); - } -} - -void S2HintMoverPro::move_double_v(const uint64_t code, uint32_t hint, const int offset) const { - switch (offset) { - case 0: move_double_v<0>(code, hint); break; - case 1: move_double_v<1>(code, hint); break; - case 2: move_double_v<2>(code, hint); break; - case 3: move_double_v<3>(code, hint); break; - case 4: move_double_v<4>(code, hint); break; - case 5: move_double_v<5>(code, hint); break; - case 6: move_double_v<6>(code, hint); break; - case 7: move_double_v<7>(code, hint); break; - case 8: move_double_v<8>(code, hint); break; - case 9: move_double_v<9>(code, hint); break; - case 10: move_double_v<10>(code, hint); break; - case 11: move_double_v<11>(code, hint); break; - case 12: move_double_v<12>(code, hint); break; - case 13: move_double_v<13>(code, hint); break; - case 14: move_double_v<14>(code, hint); break; - case 15: move_double_v<15>(code, hint); break; - default: std::unreachable(); - } -} - -void S2HintMoverPro::move_single(const uint64_t code, uint32_t hint, const int offset, int offset_) const { - uint64_t kk = MAKE_SP(offset_); - switch (offset) { - case 0: move_single<0>(code, hint, kk); break; - case 1: move_single<1>(code, hint, kk); break; - case 2: move_single<2>(code, hint, kk); break; - case 3: move_single<3>(code, hint, kk); break; - case 4: move_single<4>(code, hint, kk); break; - case 5: move_single<5>(code, hint, kk); break; - case 6: move_single<6>(code, hint, kk); break; - case 7: move_single<7>(code, hint, kk); break; - case 8: move_single<8>(code, hint, kk); break; - case 9: move_single<9>(code, hint, kk); break; - case 10: move_single<10>(code, hint, kk); break; - case 11: move_single<11>(code, hint, kk); break; - case 12: move_single<12>(code, hint, kk); break; - case 13: move_single<13>(code, hint, kk); break; - case 14: move_single<14>(code, hint, kk); break; - case 15: move_single<15>(code, hint, kk); break; - case 16: move_single<16>(code, hint, kk); break; - case 17: move_single<17>(code, hint, kk); break; - case 18: move_single<18>(code, hint, kk); break; - case 19: move_single<19>(code, hint, kk); break; - default: std::unreachable(); - } -} - -void S2HintMoverPro::next_cases(const uint64_t code, const uint64_t hint) const { - // const uint64_t mask = code | (code >> 1) | (code >> 2) | 0xFDB6DB6DB6DB6DB6; - // const int space_a = std::countr_one(mask) / 3; - // const int space_b = (63 - std::countl_one(mask)) / 3; - - const uint32_t tmp = hint; - const int space_a_ = std::countr_zero(tmp); - const int space_b_ = 31 - std::countl_zero(tmp); - - // if (space_a != space_a_) { - // std::cout << "error: " << RawCode::unsafe_create(code).to_common_code() << std::endl; - // } - // if (space_b != space_b_) { - // std::cout << "error" << RawCode::unsafe_create(code).to_common_code() << std::endl; - // } - - const uint32_t hint_ = hint >> 32; - if (space_a_ + 1 == space_b_ && space_a_ % 4 != 3) { - move_double_h(code, hint_, space_a_); - } else if (space_a_ + 4 == space_b_) { - move_double_v(code, hint_, space_a_); - } else { - move_single(code, hint_, space_a_, space_b_); - move_single(code, hint_, space_b_, space_a_); - } -} - -uint64_t S2HintMoverPro::make_hint(const uint64_t code) { - const uint64_t mask = code | (code >> 1) | (code >> 2) | 0xFDB6DB6DB6DB6DB6; - const int space_a = std::countr_one(mask) / 3; - const int space_b = (63 - std::countl_one(mask)) / 3; - return MAKE_SP(space_a) | MAKE_SP(space_b); -} diff --git a/src/core/mover/internal/s2_hint_mover.cc b/src/core/mover/internal/s2_hint_mover.cc index 2a577ab..60aa3e0 100644 --- a/src/core/mover/internal/s2_hint_mover.cc +++ b/src/core/mover/internal/s2_hint_mover.cc @@ -1,9 +1,12 @@ -#include "mover/s2_hint_mover.h" +#include "mover/mover.h" #include "raw_code/raw_code.h" using klotski::codec::RawCode; using klotski::mover::S2HintMover; +// TODO: using `CAPTURE(N + xxx)` instead of `CAPTURE(code, N + xxx)` +// also for `RELEASE_xxx` and `MAYBE_xxx` + #define ADDR(N) ((N) * 3) #define CAPTURE(code, N) (((code) >> ADDR(N)) & 0b111ULL) @@ -21,16 +24,16 @@ using klotski::mover::S2HintMover; ((code) & ~(K_MASK_2x2_ << ADDR(SRC)) | (K_MASK_2x2 << ADDR(DST))) #define RELEASE_1x1(code, SRC, DST) \ - release_(MOVE_1x1(code, SRC, DST), (0b1 << (DST))) + release_(RawCode::unsafe_create(MOVE_1x1(code, SRC, DST)), (0b1 << (DST))) #define RELEASE_1x2(code, SRC, DST) \ - release_(MOVE_1x2(code, SRC, DST), (0b11 << (DST))) + release_(RawCode::unsafe_create(MOVE_1x2(code, SRC, DST)), (0b11 << (DST))) #define RELEASE_2x1(code, SRC, DST) \ - release_(MOVE_2x1(code, SRC, DST), (0b10001 << (DST))) + release_(RawCode::unsafe_create(MOVE_2x1(code, SRC, DST)), (0b10001 << (DST))) #define RELEASE_2x2(code, SRC, DST) \ - release_(MOVE_2x2(code, SRC, DST), (0b110011 << (DST))) + release_(RawCode::unsafe_create(MOVE_2x2(code, SRC, DST)), (0b110011 << (DST))) #define MAYBE_UP(hint, N) (((hint) & (1 << ((N) - 4))) == 0) @@ -298,17 +301,18 @@ void S2HintMover::move_single(const uint64_t code, uint64_t hint, const int offs } } -void S2HintMover::next_cases(const uint64_t code, const uint64_t hint) const { - const uint64_t mask = code | (code >> 1) | (code >> 2) | 0xFDB6DB6DB6DB6DB6; +void S2HintMover::next_cases(const RawCode code, const uint64_t hint) const { + uint64_t code_ = code.unwrap(); + const uint64_t mask = code_ | (code_ >> 1) | (code_ >> 2) | 0xFDB6DB6DB6DB6DB6; const int space_a = std::countr_one(mask) / 3; const int space_b = (63 - std::countl_one(mask)) / 3; if (space_a + 1 == space_b && space_a % 4 != 3) { - move_double_h(code, hint, space_a); + move_double_h(code_, hint, space_a); } else if (space_a + 4 == space_b) { - move_double_v(code, hint, space_a); + move_double_v(code_, hint, space_a); } else { - move_single(code, hint, space_a); - move_single(code, hint, space_b); + move_single(code_, hint, space_a); + move_single(code_, hint, space_b); } } diff --git a/src/core/mover/internal/s2_mover.cc b/src/core/mover/internal/s2_mover.cc index 270a074..d4d69c1 100644 --- a/src/core/mover/internal/s2_mover.cc +++ b/src/core/mover/internal/s2_mover.cc @@ -1,8 +1,11 @@ -#include "mover/s2_mover.h" +#include "mover/mover.h" #include "raw_code/raw_code.h" -using klotski::mover::S2Mover; using klotski::codec::RawCode; +using klotski::mover::S2Mover; + +// TODO: using `CAPTURE(N + xxx)` instead of `CAPTURE(code, N + xxx)` +// also for `RELEASE_xxx` #define ADDR(N) ((N) * 3) @@ -20,13 +23,13 @@ using klotski::codec::RawCode; #define MOVE_2x2(code, SRC, DST) \ ((code) & ~(K_MASK_2x2_ << ADDR(SRC)) | (K_MASK_2x2 << ADDR(DST))) -#define RELEASE_1x1(code, SRC, DST) release_(MOVE_1x1(code, SRC, DST)) +#define RELEASE_1x1(code, SRC, DST) release_(RawCode::unsafe_create(MOVE_1x1(code, SRC, DST))) -#define RELEASE_1x2(code, SRC, DST) release_(MOVE_1x2(code, SRC, DST)) +#define RELEASE_1x2(code, SRC, DST) release_(RawCode::unsafe_create(MOVE_1x2(code, SRC, DST))) -#define RELEASE_2x1(code, SRC, DST) release_(MOVE_2x1(code, SRC, DST)) +#define RELEASE_2x1(code, SRC, DST) release_(RawCode::unsafe_create(MOVE_2x1(code, SRC, DST))) -#define RELEASE_2x2(code, SRC, DST) release_(MOVE_2x2(code, SRC, DST)) +#define RELEASE_2x2(code, SRC, DST) release_(RawCode::unsafe_create(MOVE_2x2(code, SRC, DST))) template void S2Mover::move_single(const uint64_t code) const { @@ -274,17 +277,18 @@ void S2Mover::move_single(const uint64_t code, const int offset) const { } } -void S2Mover::next_cases(const uint64_t code) const { - const uint64_t mask = code | (code >> 1) | (code >> 2) | 0xFDB6DB6DB6DB6DB6; +void S2Mover::next_cases(const RawCode code) const { + uint64_t code_ = code.unwrap(); + const uint64_t mask = code_ | (code_ >> 1) | (code_ >> 2) | 0xFDB6DB6DB6DB6DB6; const int space_a = std::countr_one(mask) / 3; const int space_b = (63 - std::countl_one(mask)) / 3; if (space_a + 1 == space_b && space_a % 4 != 3) { - move_double_h(code, space_a); + move_double_h(code_, space_a); } else if (space_a + 4 == space_b) { - move_double_v(code, space_a); + move_double_v(code_, space_a); } else { - move_single(code, space_a); - move_single(code, space_b); + move_single(code_, space_a); + move_single(code_, space_b); } } diff --git a/src/core/mover/mover.h b/src/core/mover/mover.h index 8036aca..9d8d078 100644 --- a/src/core/mover/mover.h +++ b/src/core/mover/mover.h @@ -100,4 +100,3 @@ private: } // namespace klotski::mover #include "s2_mover.h" -#include "s2_hint_mover.h" diff --git a/src/core/mover/s2_hint_mover.h b/src/core/mover/s2_hint_mover.h deleted file mode 100644 index eeaf127..0000000 --- a/src/core/mover/s2_hint_mover.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include - -namespace klotski::mover { - -class S2HintMover { -public: - using release_t = std::function; - - explicit S2HintMover(release_t release_func) : release_(std::move(release_func)) {} - - void next_cases(uint64_t code, uint64_t hint) const; - -private: - release_t release_; - - template - void move_single(uint64_t code, uint64_t hint) const; - - template - void move_double_h(uint64_t code, uint64_t hint) const; - - template - void move_double_v(uint64_t code, uint64_t hint) const; - - void move_single(uint64_t code, uint64_t hint, int offset) const; - void move_double_h(uint64_t code, uint64_t hint, int offset) const; - void move_double_v(uint64_t code, uint64_t hint, int offset) const; -}; - -} // namespace klotski::mover - -namespace klotski::mover { - -// TODO: It seems that storage space in `hint` will cause performance -// degradation, maybe remove this optimization. - -class S2HintMoverPro { -public: - using release_t = std::function; - - explicit S2HintMoverPro(release_t release_func) : release_(std::move(release_func)) {} - - void next_cases(uint64_t code, uint64_t hint) const; - - static uint64_t make_hint(uint64_t code); - -private: - release_t release_; - - template - void move_single(uint64_t code, uint32_t hint, uint32_t kk) const; - - template - void move_double_h(uint64_t code, uint32_t hint) const; - - template - void move_double_v(uint64_t code, uint32_t hint) const; - - void move_single(uint64_t code, uint32_t hint, int offset, int offset_) const; - void move_double_h(uint64_t code, uint32_t hint, int offset) const; - void move_double_v(uint64_t code, uint32_t hint, int offset) const; -}; - -} // namespace klotski::mover diff --git a/src/core/mover/s2_mover.h b/src/core/mover/s2_mover.h index ade1169..c478f32 100644 --- a/src/core/mover/s2_mover.h +++ b/src/core/mover/s2_mover.h @@ -2,15 +2,17 @@ #include +#include "raw_code/raw_code_fwd.h" + namespace klotski::mover { class S2Mover { public: - using release_t = std::function; + using release_t = std::function; explicit S2Mover(release_t release_func) : release_(std::move(release_func)) {} - void next_cases(uint64_t code) const; + void next_cases(codec::RawCode code) const; private: release_t release_; @@ -29,4 +31,29 @@ private: void move_double_v(uint64_t code, int offset) const; }; +class S2HintMover { +public: + using release_t = std::function; + + explicit S2HintMover(release_t release_func) : release_(std::move(release_func)) {} + + void next_cases(codec::RawCode code, uint64_t hint) const; + +private: + release_t release_; + + template + void move_single(uint64_t code, uint64_t hint) const; + + template + void move_double_h(uint64_t code, uint64_t hint) const; + + template + void move_double_v(uint64_t code, uint64_t hint) const; + + void move_single(uint64_t code, uint64_t hint, int offset) const; + void move_double_h(uint64_t code, uint64_t hint, int offset) const; + void move_double_v(uint64_t code, uint64_t hint, int offset) const; +}; + } // namespace klotski::mover diff --git a/src/core_test/mover/s2_mover.cc b/src/core_test/mover/s2_mover.cc index 0051aed..ce8d94f 100644 --- a/src/core_test/mover/s2_mover.cc +++ b/src/core_test/mover/s2_mover.cc @@ -27,12 +27,12 @@ TEST(S2Mover, demo) { auto s2_mover = [](RawCode src) { std::vector results {}; - auto mover = S2Mover([&results](uint64_t code) { + auto mover = S2Mover([&results](RawCode code) { // std::cout << RawCode::unsafe_create(code) << std::endl; - EXPECT_TRUE(RawCode::check(code)); + EXPECT_TRUE(RawCode::check(code.unwrap())); results.emplace_back(code); }); - mover.next_cases(src.unwrap()); + mover.next_cases(src); std::ranges::sort(results.begin(), results.end()); return results; };