diff --git a/src/klotski_core/ffi/tmain.cc b/src/klotski_core/ffi/tmain.cc index 8dc444f..42ce27d 100644 --- a/src/klotski_core/ffi/tmain.cc +++ b/src/klotski_core/ffi/tmain.cc @@ -19,8 +19,9 @@ #include "group.h" using klotski::Group; -using klotski::TypeId; using klotski::AllCases; +using klotski::GroupCase; +using klotski::GroupType; using klotski::RawCode; using klotski::ShortCode; @@ -34,40 +35,16 @@ using klotski::TYPE_ID_LIMIT; void tmain() { // printf("tmain start\n"); - auto start = clock(); +// auto start = clock(); -// Group::build_group(123, 233); +// auto ret = GroupCase::encode(CommonCode(0x1A9BF0C00)); + auto ret = GroupCase::encode(CommonCode(0x4FEA13400)); - Group::build_groups(TypeId(123)); + std::cout << "type id: " << ret.type_id << std::endl; + std::cout << "group id: " << ret.group_id << std::endl; + std::cout << "group index: " << ret.group_index << std::endl; - std::cerr << (clock() - start) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; - -// auto seed = Group::group_seed(123, 233); -// std::cout << seed << std::endl; - -// Group::group_info(CommonCode(0x1A9BF0C00)); - -// std::vector group_num; -// group_num.reserve(TYPE_ID_LIMIT); -// for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { -// group_num.emplace_back(Group::build_groups(type_id).size()); -// std::cerr << type_id << std::endl; -// } -// -// uint32_t offset = 0; -// std::vector group_offset; -// group_offset.reserve(TYPE_ID_LIMIT); -// for (auto &&tmp : group_num) { -// group_offset.emplace_back(offset); -// offset += tmp; -// } -// -// for (uint32_t i = 0; i < group_offset.size(); ++i) { -// printf("%5d, ", group_offset[i]); -// if (i % 12 == 11) { -// printf("\n"); -// } -// } +// std::cerr << (clock() - start) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; // printf("tmain exit\n"); } diff --git a/src/klotski_core/group/basic_id.cc b/src/klotski_core/group/basic_id.cc index e8f6aa9..746b06c 100644 --- a/src/klotski_core/group/basic_id.cc +++ b/src/klotski_core/group/basic_id.cc @@ -8,24 +8,24 @@ namespace klotski { using Common::range_reverse; -/// ----------------------------------------- Type ID ----------------------------------------- +/// --------------------------------------- Group Type ---------------------------------------- -TypeId::TypeId(uint32_t type_id) { +GroupType::GroupType(uint32_t type_id) { if (type_id >= TYPE_ID_LIMIT) { // invalid type id throw std::invalid_argument("type id overflow"); } type_id_ = type_id; } -TypeId::TypeId(const RawCode &raw_code) noexcept { +GroupType::GroupType(const RawCode &raw_code) noexcept { type_id_ = type_id(block_num(raw_code)); } -TypeId::TypeId(const CommonCode &common_code) noexcept { +GroupType::GroupType(const CommonCode &common_code) noexcept { type_id_ = type_id(block_num(common_code)); } -uint32_t TypeId::type_id(block_num_t &&block_num) noexcept { // block_num_t -> type_id +uint32_t GroupType::type_id(block_num_t &&block_num) noexcept { // block_num_t -> type_id /// flag -> ... 0000 0xxx 0xxx xxxx /// n_x2x n_2x1 n_1x1 auto n_x2x = block_num.n_1x2 + block_num.n_2x1; @@ -35,7 +35,7 @@ uint32_t TypeId::type_id(block_num_t &&block_num) noexcept { // block_num_t -> t /// -------------------------------------- Block Number --------------------------------------- -TypeId::block_num_t TypeId::block_num() const noexcept { // type_id -> block_num_t +GroupType::block_num_t GroupType::block_num() const noexcept { // type_id -> block_num_t auto flag = TYPE_ID_INDEX[type_id_]; auto n_2x1 = (flag >> 4) & 0b111; return block_num_t { @@ -45,7 +45,7 @@ TypeId::block_num_t TypeId::block_num() const noexcept { // type_id -> block_num }; } -TypeId::block_num_t TypeId::block_num(const RawCode &raw_code) noexcept { +GroupType::block_num_t GroupType::block_num(const RawCode &raw_code) noexcept { block_num_t result; auto tmp = raw_code.unwrap(); for (int addr = 0; addr < 20; ++addr, tmp >>= 3) { @@ -64,7 +64,7 @@ TypeId::block_num_t TypeId::block_num(const RawCode &raw_code) noexcept { return result; } -TypeId::block_num_t TypeId::block_num(const CommonCode &common_code) noexcept { +GroupType::block_num_t GroupType::block_num(const CommonCode &common_code) noexcept { block_num_t result; auto range = range_reverse(static_cast(common_code.unwrap())); for (; range; range >>= 2) { @@ -85,26 +85,26 @@ TypeId::block_num_t TypeId::block_num(const CommonCode &common_code) noexcept { /// ------------------------------------------ Group ------------------------------------------ -Group::Group(uint32_t type_id, uint32_t group_id) : type_id_(type_id) { +Group::Group(uint32_t type_id, uint32_t group_id) : type_(type_id) { if (group_id >= TYPE_ID_GROUP_NUM[type_id]) { throw std::invalid_argument("group id overflow"); } group_id_ = group_id; } -Group::Group(const TypeId &type_id, uint32_t group_id) : type_id_(type_id) { - if (group_id >= TYPE_ID_GROUP_NUM[type_id.unwrap()]) { +Group::Group(const GroupType &group_type, uint32_t group_id) : type_(group_type) { + if (group_id >= TYPE_ID_GROUP_NUM[group_type.unwrap()]) { throw std::invalid_argument("group id overflow"); } group_id_ = group_id; } -Group::Group(const RawCode &raw_code) noexcept : type_id_(TypeId(raw_code)) { - group_id_ = group_id(type_id_.unwrap(), Group::seed(raw_code)); +Group::Group(const RawCode &raw_code) noexcept : type_(GroupType(raw_code)) { + group_id_ = group_id(type_, Group::seed(raw_code)); } -Group::Group(const CommonCode &common_code) noexcept : type_id_(TypeId(common_code)) { - group_id_ = group_id(type_id_.unwrap(), Group::seed(common_code)); +Group::Group(const CommonCode &common_code) noexcept : type_(GroupType(common_code)) { + group_id_ = group_id(type_, Group::seed(common_code)); } } // namespace klotski diff --git a/src/klotski_core/group/build_cases.cc b/src/klotski_core/group/build_cases.cc index 22d35d0..e5a8ce3 100644 --- a/src/klotski_core/group/build_cases.cc +++ b/src/klotski_core/group/build_cases.cc @@ -12,9 +12,9 @@ namespace klotski { using Common::check_range; using Common::range_reverse; -/// ----------------------------------------- Type ID ----------------------------------------- +/// --------------------------------------- Group Type ---------------------------------------- -std::vector TypeId::cases() const noexcept { +std::vector GroupType::cases() const noexcept { std::vector ranges; // basic ranges of type_id ranges.reserve(TYPE_ID_SIZE[type_id_]); // over-allocation @@ -48,8 +48,8 @@ std::vector TypeId::cases() const noexcept { return all_cases; } -std::vector> TypeId::groups() const noexcept { - auto all_cases = TypeId::cases(); +std::vector> GroupType::groups() const noexcept { + auto all_cases = GroupType::cases(); std::vector> groups; auto min = std::min_element(all_cases.begin(), all_cases.end()); // search min CommonCode @@ -91,7 +91,7 @@ uint32_t Group::size(const CommonCode &common_code) noexcept { uint32_t Group::size(const RawCode &raw_code) noexcept { std::queue cache({raw_code.unwrap()}); absl::flat_hash_map cases; // - cases.reserve(TypeId::group_max_size(raw_code)); + cases.reserve(GroupType::max_size(raw_code)); cases.emplace(raw_code.unwrap(), 0b0); // without mask auto core = Core( @@ -125,7 +125,7 @@ std::vector Group::cases(const CommonCode &common_code) noexcept { std::vector Group::cases(const RawCode &raw_code) noexcept { std::queue cache({raw_code.unwrap()}); absl::flat_hash_map cases; // - cases.reserve(TypeId::group_max_size(raw_code)); + cases.reserve(GroupType::max_size(raw_code)); cases.emplace(raw_code.unwrap(), 0b0); // without mask auto core = Core( diff --git a/src/klotski_core/group/group.h b/src/klotski_core/group/group.h index ee0cc75..5c682ed 100644 --- a/src/klotski_core/group/group.h +++ b/src/klotski_core/group/group.h @@ -9,9 +9,9 @@ namespace klotski { const uint32_t TYPE_ID_LIMIT = 203; const uint32_t ALL_GROUP_NUM = 25422; -/// ----------------------------------------- Type ID ----------------------------------------- +/// --------------------------------------- Group Type ---------------------------------------- -class TypeId { +class GroupType { public: /// 1. n_1x1 + (n_1x2 + n_2x1) * 2 <= 14 /// 2. (n_1x1 != 0) && (n_2x1 != 7) @@ -27,9 +27,9 @@ private: static inline uint32_t type_id(block_num_t &&block_num) noexcept; public: - explicit TypeId(uint32_t type_id); - explicit TypeId(const RawCode &raw_code) noexcept; - explicit TypeId(const CommonCode &common_code) noexcept; + explicit GroupType(uint32_t type_id); + explicit GroupType(const RawCode &raw_code) noexcept; + explicit GroupType(const CommonCode &common_code) noexcept; /// Release raw type_id value. constexpr uint32_t unwrap() const noexcept { return type_id_; } @@ -45,9 +45,9 @@ public: static uint32_t group_num(const CommonCode &common_code) noexcept; /// Get the max group size. - uint32_t group_max_size() const noexcept; - static uint32_t group_max_size(const RawCode &raw_code) noexcept; - static uint32_t group_max_size(const CommonCode &common_code) noexcept; + uint32_t max_size() const noexcept; + static uint32_t max_size(const RawCode &raw_code) noexcept; + static uint32_t max_size(const CommonCode &common_code) noexcept; /// Get all seeds of the current type_id. std::vector seeds() const noexcept; @@ -62,20 +62,20 @@ public: /// ------------------------------------------ Group ------------------------------------------ class Group { - TypeId type_id_; + GroupType type_; uint32_t group_id_; - static uint32_t group_id(uint32_t type_id, const CommonCode &seed) noexcept; + static uint32_t group_id(GroupType group_type, CommonCode seed) noexcept; public: Group(uint32_t type_id, uint32_t group_id); - Group(const TypeId &type_id, uint32_t group_id); + Group(const GroupType &group_type, uint32_t group_id); explicit Group(const RawCode &raw_code) noexcept; explicit Group(const CommonCode &common_code) noexcept; /// Release raw type_id / group_id value. constexpr uint32_t unwrap() const noexcept { return group_id_; } - constexpr uint32_t type_id() const noexcept { return type_id_.unwrap(); } + constexpr uint32_t type_id() const noexcept { return type_.unwrap(); } /// Get the size of the current group. uint32_t size() const noexcept; @@ -96,6 +96,8 @@ public: /// --------------------------------------- Group Case ---------------------------------------- class GroupCase { + static uint32_t group_id(GroupType group_type, CommonCode seed) noexcept; + public: struct info_t { uint16_t type_id; @@ -113,7 +115,7 @@ public: /// ---------------------------------------- Operators ---------------------------------------- -inline bool operator==(const TypeId &t1, const TypeId &t2) { +inline bool operator==(const GroupType &t1, const GroupType &t2) { return t1.unwrap() == t2.unwrap(); } @@ -121,7 +123,7 @@ inline bool operator==(const Group &g1, const Group &g2) { return g1.type_id() == g2.type_id() && g1.unwrap() == g2.unwrap(); } -inline bool operator==(const TypeId::block_num_t &b1, const TypeId::block_num_t &b2) { +inline bool operator==(const GroupType::block_num_t &b1, const GroupType::block_num_t &b2) { return (b1.n_1x1 == b2.n_1x1) && (b1.n_1x2 == b2.n_1x2) && (b1.n_2x1 == b2.n_2x1); } @@ -130,8 +132,8 @@ inline bool operator==(const GroupCase::info_t &i1, const GroupCase::info_t &i2) } inline bool operator!=(const Group &g1, const Group &g2) { return !(g1 == g2); } -inline bool operator!=(const TypeId &t1, const TypeId &t2) { return !(t1 == t2); } +inline bool operator!=(const GroupType &t1, const GroupType &t2) { return !(t1 == t2); } inline bool operator!=(const GroupCase::info_t &i1, const GroupCase::info_t &i2) { return !(i1 == i2); } -inline bool operator!=(const TypeId::block_num_t &b1, const TypeId::block_num_t &b2) { return !(b1 == b2); } +inline bool operator!=(const GroupType::block_num_t &b1, const GroupType::block_num_t &b2) { return !(b1 == b2); } } // namespace klotski diff --git a/src/klotski_core/group/group_info.cc b/src/klotski_core/group/group_info.cc index 8c31be9..8bb9335 100644 --- a/src/klotski_core/group/group_info.cc +++ b/src/klotski_core/group/group_info.cc @@ -1,52 +1,61 @@ #include #include "group.h" #include "type_id.h" -#include "group_seeds.h" #include namespace klotski { -/// ----------------------------------------- Type ID ----------------------------------------- +/// --------------------------------------- Group Type ---------------------------------------- -uint32_t TypeId::group_num() const noexcept { +uint32_t GroupType::group_num() const noexcept { return TYPE_ID_GROUP_NUM[type_id_]; } -uint32_t TypeId::group_num(const RawCode &raw_code) noexcept { - return TypeId(raw_code).group_num(); +uint32_t GroupType::group_num(const RawCode &raw_code) noexcept { + return GroupType(raw_code).group_num(); } -uint32_t TypeId::group_num(const CommonCode &common_code) noexcept { - return TypeId(common_code).group_num(); +uint32_t GroupType::group_num(const CommonCode &common_code) noexcept { + return GroupType(common_code).group_num(); } -uint32_t TypeId::group_max_size() const noexcept { +uint32_t GroupType::max_size() const noexcept { return TYPE_ID_GROUP_MAX_SIZE[type_id_]; } -uint32_t TypeId::group_max_size(const RawCode &raw_code) noexcept { - return TypeId(raw_code).group_max_size(); +uint32_t GroupType::max_size(const RawCode &raw_code) noexcept { + return GroupType(raw_code).max_size(); } -uint32_t TypeId::group_max_size(const CommonCode &common_code) noexcept { - return TypeId(common_code).group_max_size(); +uint32_t GroupType::max_size(const CommonCode &common_code) noexcept { + return GroupType(common_code).max_size(); } /// --------------------------------------- Group Case ---------------------------------------- GroupCase::info_t GroupCase::encode(const RawCode &raw_code) noexcept { - - // TODO: function body - - return {}; + return encode(raw_code.to_common_code()); } GroupCase::info_t GroupCase::encode(const CommonCode &common_code) noexcept { - - // TODO: function body - - return {}; + auto cases = Group::cases(common_code); + std::vector group(cases.begin(), cases.end()); + + uint32_t group_index = 0; + for (auto &&code: group) { + if (code < common_code) { + ++group_index; // locate group index + } + } + + GroupType type = GroupType(common_code); + auto seed = *std::min_element(group.begin(), group.end()); + return { + .type_id = static_cast(type.unwrap()), + .group_id = static_cast(group_id(type, seed)), + .group_index = group_index, + }; } CommonCode GroupCase::parse(const info_t &info) { diff --git a/src/klotski_core/group/seeds.cc b/src/klotski_core/group/seeds.cc index 031e691..7b32b22 100644 --- a/src/klotski_core/group/seeds.cc +++ b/src/klotski_core/group/seeds.cc @@ -7,13 +7,13 @@ namespace klotski { -std::vector TypeId::seeds() const noexcept { +std::vector GroupType::seeds() const noexcept { auto offset = GROUP_SEEDS + TYPE_ID_OFFSET[type_id_]; // type id offset return {offset, offset + TYPE_ID_GROUP_NUM[type_id_]}; } CommonCode Group::seed() const noexcept { // group_id -> seed - auto offset = TYPE_ID_OFFSET[type_id_.unwrap()]; // type id offset + auto offset = TYPE_ID_OFFSET[type_.unwrap()]; // type id offset auto index = offset + GROUP_SEEDS_INDEX[offset + group_id_]; return CommonCode::unsafe_create(GROUP_SEEDS[index]); } @@ -28,11 +28,19 @@ CommonCode Group::seed(const CommonCode &common_code) noexcept { return seed(common_code.to_raw_code()); } -uint32_t Group::group_id(uint32_t type_id, const CommonCode &seed) noexcept { // seed -> group_id +static inline uint32_t load_group_id(uint32_t type_id, uint64_t seed) { // seed -> group_id auto start = GROUP_SEEDS + TYPE_ID_OFFSET[type_id]; auto end = start + TYPE_ID_GROUP_NUM[type_id]; - auto index = std::lower_bound(start, end, seed.unwrap()) - GROUP_SEEDS; + auto index = std::lower_bound(start, end, seed) - GROUP_SEEDS; return GROUP_SEEDS_INDEX_REV[index]; } +uint32_t Group::group_id(GroupType group_type, CommonCode seed) noexcept { + return load_group_id(group_type.unwrap(), seed.unwrap()); +} + +uint32_t GroupCase::group_id(GroupType group_type, CommonCode seed) noexcept { + return load_group_id(group_type.unwrap(), seed.unwrap()); +} + } // namespace klotski