Browse Source

feat: add demo of `S2Mover`

master
Dnomd343 4 weeks ago
parent
commit
4e6626595e
  1. 1
      src/core/CMakeLists.txt
  2. 59
      src/core/main.cc
  3. 403
      src/core/mover/internal/s2_mover.cc
  4. 2
      src/core/mover/mover.h
  5. 24
      src/core/mover/s2_mover.h

1
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

59
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();

403
src/core/mover/internal/s2_mover.cc

@ -0,0 +1,403 @@
#include <iostream>
#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);
}
}

2
src/core/mover/mover.h

@ -98,3 +98,5 @@ private:
};
} // namespace klotski::mover
#include "s2_mover.h"

24
src/core/mover/s2_mover.h

@ -0,0 +1,24 @@
#pragma once
#include <functional>
namespace klotski::mover {
class S2Mover {
public:
using release_t = std::function<void(uint64_t)>;
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
Loading…
Cancel
Save