Browse Source

feat: locate group info

master
Dnomd343 1 year ago
parent
commit
91cb4df89c
  1. 41
      src/klotski_core/ffi/tmain.cc
  2. 30
      src/klotski_core/group/basic_id.cc
  3. 12
      src/klotski_core/group/build_cases.cc
  4. 34
      src/klotski_core/group/group.h
  5. 49
      src/klotski_core/group/group_info.cc
  6. 16
      src/klotski_core/group/seeds.cc

41
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<uint32_t> 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<uint32_t> 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");
}

30
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<uint32_t>(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

12
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<CommonCode> TypeId::cases() const noexcept {
std::vector<CommonCode> GroupType::cases() const noexcept {
std::vector<uint32_t> ranges; // basic ranges of type_id
ranges.reserve(TYPE_ID_SIZE[type_id_]); // over-allocation
@ -48,8 +48,8 @@ std::vector<CommonCode> TypeId::cases() const noexcept {
return all_cases;
}
std::vector<std::vector<CommonCode>> TypeId::groups() const noexcept {
auto all_cases = TypeId::cases();
std::vector<std::vector<CommonCode>> GroupType::groups() const noexcept {
auto all_cases = GroupType::cases();
std::vector<std::vector<CommonCode>> 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<uint64_t> cache({raw_code.unwrap()});
absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask>
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<RawCode> Group::cases(const CommonCode &common_code) noexcept {
std::vector<RawCode> Group::cases(const RawCode &raw_code) noexcept {
std::queue<uint64_t> cache({raw_code.unwrap()});
absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask>
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(

34
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<CommonCode> 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

49
src/klotski_core/group/group_info.cc

@ -1,52 +1,61 @@
#include <algorithm>
#include "group.h"
#include "type_id.h"
#include "group_seeds.h"
#include <iostream>
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<CommonCode> 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<uint16_t>(type.unwrap()),
.group_id = static_cast<uint16_t>(group_id(type, seed)),
.group_index = group_index,
};
}
CommonCode GroupCase::parse(const info_t &info) {

16
src/klotski_core/group/seeds.cc

@ -7,13 +7,13 @@
namespace klotski {
std::vector<CommonCode> TypeId::seeds() const noexcept {
std::vector<CommonCode> 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

Loading…
Cancel
Save