Browse Source

feat: group cases fast codec

master
Dnomd343 2 years ago
parent
commit
6ecaec7cee
  1. 32
      src/klotski_core/ffi/tmain.cc
  2. 19
      src/klotski_core/group/group.h
  3. 100
      src/klotski_core/group/group_info.cc

32
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;

19
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<uint32_t> group_info;
static std::vector<ShortCodes> 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);

100
src/klotski_core/group/group_info.cc

@ -1,4 +1,5 @@
#include <algorithm>
#include <stdexcept>
#include "group.h"
#include "type_id.h"
@ -6,6 +7,9 @@
namespace klotski {
std::vector<uint32_t> GroupCase::group_info(SHORT_CODE_LIMIT);
std::vector<ShortCodes> 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<uint16_t>(GroupType(common_code).unwrap()),
.group_id = static_cast<uint16_t>(info >> 20),
.group_index = info & 0xFFFFF,
};
}
std::vector<uint32_t> group_info(SHORT_CODE_LIMIT);
std::vector<std::vector<ShortCode>> group_data[TYPE_ID_LIMIT];
/// ------------------------------------ Group Case Index -------------------------------------
void GroupCase::speed_up() {
ShortCode::speed_up(ShortCode::FAST);
auto convert = [](const std::vector<RawCode> &raw_codes) -> std::vector<CommonCode> {
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

Loading…
Cancel
Save