From 6ecaec7ceefc9c9f19f69262a928e0ec2a6d2b0b Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Mon, 1 May 2023 16:05:18 +0800 Subject: [PATCH] feat: group cases fast codec --- src/klotski_core/ffi/tmain.cc | 32 ++++----- src/klotski_core/group/group.h | 19 ++++- src/klotski_core/group/group_info.cc | 100 +++++++++++++++------------ 3 files changed, 82 insertions(+), 69 deletions(-) diff --git a/src/klotski_core/ffi/tmain.cc b/src/klotski_core/ffi/tmain.cc index e4150a7..61d77b2 100644 --- a/src/klotski_core/ffi/tmain.cc +++ b/src/klotski_core/ffi/tmain.cc @@ -37,26 +37,18 @@ void tmain() { // auto start = clock(); - GroupCase::demo(); - -// auto ret = GroupCase::encode(CommonCode(0x1A9BF0C00)); -// auto ret = GroupCase::encode(CommonCode(0x4FEA13400)); -// -// 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::cout << GroupCase::parse({ -// .type_id = 169, -// .group_id = 1, -// .group_index = 7472, -// }) << std::endl; -// -// std::cout << GroupCase::parse({ -// .type_id = 164, -// .group_id = 0, -// .group_index = 30833, -// }) << std::endl; + + GroupCase::speed_up(); + + // 1A9BF0C00 -> 169-1-7472 + // 4FEA13400 -> 164-0-30833 + std::cout << GroupCase::parse({169, 1, 7472}) << std::endl; + std::cout << GroupCase::parse({164, 0, 30833}) << std::endl; + auto i1 = GroupCase::encode(CommonCode(0x1A9BF0C00)); + auto i2 = GroupCase::encode(CommonCode(0x4FEA13400)); + std::cout << i1.type_id << "-" << i1.group_id << "-" << i1.group_index << std::endl; + std::cout << i2.type_id << "-" << i2.group_id << "-" << i2.group_index << std::endl; + // std::cerr << (clock() - start) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; diff --git a/src/klotski_core/group/group.h b/src/klotski_core/group/group.h index 74be9bf..2185deb 100644 --- a/src/klotski_core/group/group.h +++ b/src/klotski_core/group/group.h @@ -153,8 +153,6 @@ public: /// --------------------------------------- Group Case ---------------------------------------- class GroupCase { - static uint32_t group_id(GroupType group_type, CommonCode seed) noexcept; - public: struct info_t { uint16_t type_id; @@ -162,7 +160,22 @@ public: uint32_t group_index; }; - static void demo(); +private: + static std::vector group_info; + static std::vector group_data[TYPE_ID_LIMIT]; + + static void build_index(GroupType group_type) noexcept; + + static CommonCode fast_decode(const info_t &info); + static CommonCode tiny_decode(const info_t &info); + static info_t fast_encode(const CommonCode &common_code) noexcept; + static info_t tiny_encode(const CommonCode &common_code) noexcept; + + static uint32_t group_id(GroupType group_type, CommonCode seed) noexcept; + +public: + /// Build group cases accelerated index. + static void speed_up(); /// Get the CommonCode using the group info. static CommonCode parse(const info_t &info); diff --git a/src/klotski_core/group/group_info.cc b/src/klotski_core/group/group_info.cc index eb236d5..6823df6 100644 --- a/src/klotski_core/group/group_info.cc +++ b/src/klotski_core/group/group_info.cc @@ -1,4 +1,5 @@ #include +#include #include "group.h" #include "type_id.h" @@ -6,6 +7,9 @@ namespace klotski { +std::vector GroupCase::group_info(SHORT_CODE_LIMIT); +std::vector GroupCase::group_data[TYPE_ID_LIMIT]; + /// --------------------------------------- Group Type ---------------------------------------- uint32_t GroupType::group_num() const noexcept { @@ -34,22 +38,33 @@ uint32_t GroupType::max_size(const CommonCode &common_code) noexcept { /// --------------------------------------- Group Case ---------------------------------------- +CommonCode GroupCase::parse(const info_t &info) { +// return tiny_decode(info); + return fast_decode(info); +} + GroupCase::info_t GroupCase::encode(const RawCode &raw_code) noexcept { return encode(raw_code.to_common_code()); } -CommonCode GroupCase::parse(const info_t &info) { +GroupCase::info_t GroupCase::encode(const CommonCode &common_code) noexcept { +// return tiny_encode(common_code); + return fast_encode(common_code); +} + +/// ------------------------------------ Group Case Codec ------------------------------------- + +CommonCode GroupCase::tiny_decode(const info_t &info) { auto cases = Group(info.type_id, info.group_id).cases(); if (cases.size() <= info.group_index) { throw std::invalid_argument("group index overflow"); // check group index } - auto group = CommonCode::convert(cases); std::nth_element(group.begin(), group.begin() + info.group_index, group.end()); return group[info.group_index]; // located nth as target } -GroupCase::info_t GroupCase::encode(const CommonCode &common_code) noexcept { +GroupCase::info_t GroupCase::tiny_encode(const CommonCode &common_code) noexcept { uint32_t group_index = 0; auto group = CommonCode::convert(Group::cases(common_code)); for (auto &&tmp: group) { @@ -57,7 +72,6 @@ GroupCase::info_t GroupCase::encode(const CommonCode &common_code) noexcept { ++group_index; // locate group index } } - GroupType type = GroupType(common_code); auto seed = *std::min_element(group.begin(), group.end()); return { @@ -67,56 +81,50 @@ GroupCase::info_t GroupCase::encode(const CommonCode &common_code) noexcept { }; } -/// ------------------------------------- Group Case Fast ------------------------------------- - -void GroupCase::demo() { - std::cout << "ok" << std::endl; +CommonCode GroupCase::fast_decode(const info_t &info) { + if (info.type_id >= TYPE_ID_LIMIT) { + throw std::invalid_argument("type id overflow"); + } + if (info.group_id >= TYPE_ID_GROUP_NUM[info.type_id]) { + throw std::invalid_argument("group id overflow"); + } + auto &target_group = group_data[info.type_id][info.group_id]; + if (info.group_index >= target_group.size()) { + throw std::invalid_argument("group index overflow"); + } + return target_group[info.group_index].to_common_code(); +} - // short code -> group_id + group_index +GroupCase::info_t GroupCase::fast_encode(const CommonCode &common_code) noexcept { + auto info = group_info[common_code.to_short_code().unwrap()]; + return { + .type_id = static_cast(GroupType(common_code).unwrap()), + .group_id = static_cast(info >> 20), + .group_index = info & 0xFFFFF, + }; +} - std::vector group_info(SHORT_CODE_LIMIT); - std::vector> group_data[TYPE_ID_LIMIT]; +/// ------------------------------------ Group Case Index ------------------------------------- +void GroupCase::speed_up() { ShortCode::speed_up(ShortCode::FAST); - - auto convert = [](const std::vector &raw_codes) -> std::vector { - return {raw_codes.begin(), raw_codes.end()}; - }; - for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { - auto tid = GroupType(type_id); - - group_data[type_id].resize(tid.group_num()); - - for (uint32_t group_id = 0; group_id < tid.group_num(); ++group_id) { - auto group = Group(tid, group_id); - - auto cases = convert(group.cases()); - std::sort(cases.begin(), cases.end()); - - for (uint32_t group_index = 0; group_index < cases.size(); ++group_index) { - auto short_code = cases[group_index].to_short_code(); - group_info[short_code.unwrap()] = (group_id << 20) | group_index; - group_data[type_id][group_id].emplace_back(short_code); - } - } + GroupCase::build_index(GroupType(type_id)); std::cerr << type_id << std::endl; } +} - - std::cout << group_data[169][1][7472].to_common_code() << std::endl; - std::cout << group_data[164][0][30833].to_common_code() << std::endl; - - auto src_1 = CommonCode(0x1A9BF0C00); - auto tmp_1 = group_info[src_1.to_short_code().unwrap()]; - std::cout << GroupType(src_1).unwrap() << "-" - << (tmp_1 >> 20) << "-" << (tmp_1 & 0xFFFFF) << std::endl; - - auto src_2 = CommonCode(0x4FEA13400); - auto tmp_2 = group_info[src_2.to_short_code().unwrap()]; - std::cout << GroupType(src_2).unwrap() << "-" - << (tmp_2 >> 20) << "-" << (tmp_2 & 0xFFFFF) << std::endl; - +void GroupCase::build_index(GroupType group_type) noexcept { + group_data[group_type.unwrap()].resize(group_type.group_num()); + for (uint32_t group_id = 0; group_id < group_type.group_num(); ++group_id) { + auto cases = CommonCode::convert(Group(group_type, group_id).cases()); + std::sort(cases.begin(), cases.end()); + for (uint32_t group_index = 0; group_index < cases.size(); ++group_index) { + auto short_code = cases[group_index].to_short_code(); + group_info[short_code.unwrap()] = (group_id << 20) | group_index; + group_data[group_type.unwrap()][group_id].emplace_back(short_code); + } + } } } // namespace klotski