diff --git a/src/core/group/group.h b/src/core/group/group.h index 65c7d0e..d451680 100644 --- a/src/core/group/group.h +++ b/src/core/group/group.h @@ -267,14 +267,31 @@ public: uint32_t case_id; }; - // TODO: allow cal Group directly + static codec::CommonCode obtain_code(CaseInfo info) { + if (fast_) { + return fast_obtain_code(info); + } + return tiny_obtain_code(info); + } + + CaseInfo obtain_info(codec::CommonCode common_code); + + // TODO: allow cal Group directly -> `obtain_group` + + static inline bool fast_ {false}; + + static inline std::mutex busy_ {}; static void build(); - static codec::CommonCode fast_parse(CaseInfo info); + static codec::CommonCode fast_obtain_code(CaseInfo info); + + static CaseInfo fast_obtain_info(codec::ShortCode short_code); + static CaseInfo fast_obtain_info(codec::CommonCode common_code); - static CaseInfo fast_obtain(codec::ShortCode short_code); + static codec::CommonCode tiny_obtain_code(CaseInfo info); + static CaseInfo tiny_obtain_info(codec::CommonCode common_code); }; class GroupCases { diff --git a/src/core/group/internal/group_cases_pro.cc b/src/core/group/internal/group_cases_pro.cc index 2061726..0a29294 100644 --- a/src/core/group/internal/group_cases_pro.cc +++ b/src/core/group/internal/group_cases_pro.cc @@ -1,5 +1,7 @@ #include +#include + #include "group/group.h" using klotski::codec::ShortCode; @@ -14,6 +16,8 @@ using klotski::cases::ALL_GROUP_NUM; using klotski::cases::TYPE_ID_LIMIT; using klotski::cases::ALL_CASES_NUM_; +using klotski::cases::GROUP_DATA; + struct case_info_t { uint32_t pattern_id : 10; uint32_t toward_id : 2; @@ -84,9 +88,12 @@ void GroupCasesPro::build() { static auto data_2 = build_tmp_data(); ru_data = &data_1; rev_data = &data_2; + + // TODO: using std::mutex `busy_` + fast_ = true; } -CommonCode GroupCasesPro::fast_parse(CaseInfo info) { +CommonCode GroupCasesPro::fast_obtain_code(CaseInfo info) { auto flat_id = PATTERN_OFFSET[info.group.type_id()] + info.group.pattern_id(); @@ -108,7 +115,7 @@ CommonCode GroupCasesPro::fast_parse(CaseInfo info) { return CommonCode::unsafe_create(head << 32 | range); } -GroupCasesPro::CaseInfo GroupCasesPro::fast_obtain(codec::ShortCode short_code) { +GroupCasesPro::CaseInfo GroupCasesPro::fast_obtain_info(ShortCode short_code) { uint16_t type_id = GroupUnion::from_short_code(short_code).unwrap(); // NOTE: need to convert as CommonCode uint16_t pattern_id = (*rev_data)[short_code.unwrap()].pattern_id; uint16_t toward_id = (*rev_data)[short_code.unwrap()].toward_id; @@ -119,3 +126,73 @@ GroupCasesPro::CaseInfo GroupCasesPro::fast_obtain(codec::ShortCode short_code) .case_id = case_id, }; } + +GroupCasesPro::CaseInfo GroupCasesPro::fast_obtain_info(CommonCode common_code) { + auto short_code = common_code.to_short_code(); + uint16_t type_id = GroupUnion::from_common_code(common_code).unwrap(); + uint16_t pattern_id = (*rev_data)[short_code.unwrap()].pattern_id; + uint16_t toward_id = (*rev_data)[short_code.unwrap()].toward_id; + auto case_id = (*rev_data)[short_code.unwrap()].case_id; + + return CaseInfo { + .group = Group::unsafe_create(type_id, pattern_id, (Group::Toward)toward_id), + .case_id = case_id, + }; +} + +CommonCode GroupCasesPro::tiny_obtain_code(CaseInfo info) { + auto cases = info.group.cases(); + uint64_t head = 0; + + for (;;) { + if (info.case_id >= cases[head].size()) { + info.case_id -= cases[head].size(); + ++head; + } else { + break; + } + } + + auto range = cases[head][info.case_id]; + return CommonCode::unsafe_create(head << 32 | range); +} + +// NOTE: copy directly from Group impl +static std::unordered_map build_map_data() { + // NOTE: using CommonCode as map key + std::unordered_map data; + data.reserve(GROUP_DATA.size()); + for (auto raw : GROUP_DATA) { + uint32_t type_id = (raw >> 12) & 0b11111111; + uint32_t pattern_id = (raw >> 2) & 0b1111111111; + uint32_t toward = raw & 0b11; + auto seed = CommonCode::unsafe_create(raw >> 20).unwrap(); + auto group = Group::unsafe_create(type_id, pattern_id, (Group::Toward)toward); + data.emplace(seed, group); + } + return data; +} + +GroupCasesPro::CaseInfo GroupCasesPro::tiny_obtain_info(CommonCode common_code) { + auto raw_codes = Group_extend(common_code.to_raw_code()); + std::vector common_codes; + common_codes.reserve(raw_codes.size()); + for (auto raw_code : raw_codes) { + common_codes.emplace_back(raw_code.to_common_code()); + } + + static auto map_data = build_map_data(); // TODO: shared map data with Group::from_raw_code + + auto seed = std::min_element(common_codes.begin(), common_codes.end()); + auto group = map_data.at(seed->unwrap()); + + // TODO: try to perf it + std::sort(common_codes.begin(), common_codes.end()); + auto tmp = std::lower_bound(common_codes.begin(), common_codes.end(), common_code); + auto case_id = tmp - common_codes.begin(); + + return CaseInfo { + .group = group, + .case_id = (uint32_t)case_id, + }; +} diff --git a/src/core/main.cc b/src/core/main.cc index 61fe3da..c2776bf 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -60,18 +60,24 @@ int main() { // std::cout << data_s.size() << std::endl; // std::cout << data_c.size() << std::endl; - auto group = Group::from_common_code(CommonCode::unsafe_create(0x1A9BF0C00)); - std::cout << group.type_id() << std::endl; - std::cout << group.pattern_id() << std::endl; - std::cout << (int)group.toward() << std::endl; +// auto group = Group::from_common_code(CommonCode::unsafe_create(0x1A9BF0C00)); +// std::cout << group.type_id() << std::endl; +// std::cout << group.pattern_id() << std::endl; +// std::cout << (int)group.toward() << std::endl; -// GroupCasesPro::build(); -// -// auto kk = GroupCasesPro::fast_obtain(CommonCode::unsafe_create(0x1A9BF0C00).to_short_code()); -// std::cout << std::format("{}-{}-{}-{}", kk.group.type_id(), kk.group.pattern_id(), (int)kk.group.toward(), kk.case_id) << std::endl; -// -// auto code = GroupCasesPro::fast_parse(kk); -// std::cout << code << std::endl; + GroupCasesPro::build(); + + auto kk = GroupCasesPro::fast_obtain_info(CommonCode::unsafe_create(0x1A9BF0C00)); + std::cout << std::format("{}-{}-{}-{}\n", kk.group.type_id(), kk.group.pattern_id(), (int)kk.group.toward(), kk.case_id); + + auto code_1 = GroupCasesPro::fast_obtain_code(kk); + std::cout << code_1 << std::endl; + + auto pp = GroupCasesPro::tiny_obtain_info(CommonCode::unsafe_create(0x1A9BF0C00)); + std::cout << std::format("{}-{}-{}-{}\n", pp.group.type_id(), pp.group.pattern_id(), (int)pp.group.toward(), pp.case_id); + + auto code_2 = GroupCasesPro::tiny_obtain_code(pp); + std::cout << code_2 << std::endl; // const auto common_code = CommonCode::unsafe_create(0x1A9BF0C00); // const auto group = Group::from_common_code(common_code);