Browse Source

update: adjust function attribution

master
Dnomd343 2 years ago
parent
commit
f7ec4f1ff0
  1. 32
      src/klotski_core/group/build_cases.cc
  2. 46
      src/klotski_core/group/group.h
  3. 2
      src/klotski_core/group/group_info.cc
  4. 20
      src/klotski_core/group/seeds.cc
  5. 18
      test/group/build_cases.cc

32
src/klotski_core/group/build_cases.cc

@ -12,28 +12,28 @@ namespace klotski {
using Common::check_range;
using Common::range_reverse;
uint32_t Group::group_size(const GroupId &group_id) {
return group_size(group_seed(group_id));
uint32_t GroupId::size() const noexcept {
return size(seed());
}
uint32_t Group::group_size(const CommonCode &common_code) {
return group_size(common_code.to_raw_code());
uint32_t GroupId::size(const CommonCode &common_code) noexcept {
return GroupId::size(common_code.to_raw_code());
}
std::vector<RawCode> Group::group_cases(const CommonCode &common_code) {
return group_cases(common_code.to_raw_code());
std::vector<RawCode> Group::cases(const CommonCode &common_code) noexcept {
return cases(common_code.to_raw_code());
}
std::vector<CommonCode> Group::build_group(const GroupId &group_id) {
auto cases = group_cases(group_seed(group_id));
auto cases = Group::cases(group_id.seed());
return {cases.begin(), cases.end()};
}
std::vector<CommonCode> Group::all_cases(const TypeId &type_id) {
std::vector<CommonCode> TypeId::all_cases() const noexcept {
std::vector<uint32_t> ranges; // basic ranges of type_id
ranges.reserve(TYPE_ID_SIZE[type_id.unwrap()]); // over-allocation
ranges.reserve(TYPE_ID_SIZE[type_id_]); // over-allocation
auto tmp = type_id.block_num();
auto tmp = block_num();
BasicRanges::generate(ranges, { // generate target ranges
.n1 = 16 - tmp.n_1x1 - (tmp.n_1x2 + tmp.n_2x1) * 2, /// space -> 00
.n2 = tmp.n_1x2, /// 1x2 -> 01
@ -45,7 +45,7 @@ std::vector<CommonCode> Group::all_cases(const TypeId &type_id) {
}
std::vector<CommonCode> all_cases;
all_cases.reserve(TYPE_ID_SIZE[type_id.unwrap()]);
all_cases.reserve(TYPE_ID_SIZE[type_id_]);
for (uint64_t head = 0; head < 15; ++head) { // address of 2x2 block
/// head -> 0/1/2 / 4/5/6 / 8/9/10 / 12/13/14
if ((head & 0b11) == 0b11) {
@ -63,7 +63,7 @@ std::vector<CommonCode> Group::all_cases(const TypeId &type_id) {
return all_cases;
}
uint32_t Group::group_size(const RawCode &raw_code) {
uint32_t GroupId::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(Group::group_max_size(raw_code));
@ -87,7 +87,7 @@ uint32_t Group::group_size(const RawCode &raw_code) {
return cases.size();
}
std::vector<RawCode> Group::group_cases(const RawCode &raw_code) {
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(Group::group_max_size(raw_code));
@ -118,11 +118,11 @@ std::vector<RawCode> Group::group_cases(const RawCode &raw_code) {
}
std::vector<std::vector<CommonCode>> Group::build_groups(const TypeId &type_id) {
auto all_cases = Group::all_cases(type_id);
auto all_cases = type_id.all_cases();
std::vector<std::vector<CommonCode>> groups;
auto min = std::min_element(all_cases.begin(), all_cases.end()); // search min CommonCode
auto first_group = group_cases(min->to_raw_code()); // expand the first group
auto first_group = cases(min->to_raw_code()); // expand the first group
groups.emplace_back(first_group.begin(), first_group.end());
if (first_group.size() == all_cases.size()) {
return groups; // only contains one group
@ -133,7 +133,7 @@ std::vector<std::vector<CommonCode>> Group::build_groups(const TypeId &type_id)
cases.erase(tmp); // remove elements from first group
}
while (!cases.empty()) {
auto group = group_cases(cases.begin()->to_raw_code());
auto group = Group::cases(cases.begin()->to_raw_code());
groups.emplace_back(group.begin(), group.end()); // release new group
for (auto &&tmp : *(groups.end() - 1)) {
cases.erase(tmp); // remove selected cases

46
src/klotski_core/group/group.h

@ -38,6 +38,12 @@ public:
block_num_t block_num() const noexcept;
static block_num_t block_num(const RawCode &raw_code) noexcept;
static block_num_t block_num(const CommonCode &common_code) noexcept;
/// Get all seeds in the specified type id.
std::vector<CommonCode> seeds() const noexcept;
/// Search for all cases of the specified type_id.
std::vector<CommonCode> all_cases() const noexcept;
};
inline bool operator==(const TypeId &t1, const TypeId &t2) {
@ -69,6 +75,16 @@ public:
/// 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(); }
/// Get the size of the specified group.
uint32_t size() const noexcept;
static uint32_t size(const RawCode &raw_code) noexcept;
static uint32_t size(const CommonCode &common_code) noexcept;
/// Get the minimum CommonCode of the specified group.
CommonCode seed() const noexcept;
static CommonCode seed(const RawCode &raw_code) noexcept;
static CommonCode seed(const CommonCode &common_code) noexcept;
};
inline bool operator==(const GroupId &g1, const GroupId &g2) {
@ -83,36 +99,16 @@ inline bool operator!=(const GroupId &g1, const GroupId &g2) {
class Group {
public:
/// ----------------------------------- group seeds -----------------------------------
/// Get the size of the specified group.
static uint32_t group_size(const GroupId &group_id);
static uint32_t group_size(const RawCode &raw_code);
static uint32_t group_size(const CommonCode &common_code);
/// Get the minimum CommonCode of the specified group.
static CommonCode group_seed(const GroupId &group_id);
static CommonCode group_seed(const RawCode &raw_code);
static CommonCode group_seed(const CommonCode &common_code);
/// Get all seeds in the specified type id.
static std::vector<CommonCode> group_seeds(const TypeId &type_id);
/// --------------------------------- cases expansion ---------------------------------
/// Search for all cases of the specified type_id.
static std::vector<CommonCode> all_cases(const TypeId &type_id);
/// Search for all derivatives that a case can produce.
static std::vector<RawCode> group_cases(const RawCode &raw_code);
static std::vector<RawCode> group_cases(const CommonCode &common_code);
static std::vector<RawCode> cases(const RawCode &raw_code) noexcept;
static std::vector<RawCode> cases(const CommonCode &common_code) noexcept;
/// Calculate the specified group in the specified group_id.
static std::vector<CommonCode> build_group(const GroupId &group_id);
/// Calculate all groups in the specified type_id.
static std::vector<std::vector<CommonCode>> build_groups(const TypeId &type_id);
/// Calculate the specified group using type_id and group_id.
static std::vector<CommonCode> build_group(const GroupId &group_id);
/// ----------------------------------- group info ------------------------------------
struct group_info_t {

2
src/klotski_core/group/group_info.cc

@ -26,7 +26,7 @@ Group::group_info_t Group::group_info(const CommonCode &common_code) {
uint32_t end = start + TYPE_ID_GROUP_NUM[type_id];
std::cout << "range: [" << start << ", " << end << ")" << std::endl;
auto group = Group::group_cases(common_code);
auto group = Group::cases(common_code);
std::vector<CommonCode> g(group.begin(), group.end());
auto seed = std::min_element(g.begin(), g.end());
std::cout << "seed: " << *seed << std::endl;

20
src/klotski_core/group/seeds.cc

@ -7,25 +7,25 @@
namespace klotski {
CommonCode Group::group_seed(const CommonCode &common_code) {
return group_seed(common_code.to_raw_code());
CommonCode GroupId::seed(const CommonCode &common_code) noexcept {
return seed(common_code.to_raw_code());
}
CommonCode Group::group_seed(const RawCode &raw_code) {
auto cases = group_cases(raw_code);
CommonCode GroupId::seed(const RawCode &raw_code) noexcept {
auto cases = Group::cases(raw_code);
std::vector<CommonCode> group(cases.begin(), cases.end());
return *std::min_element(group.begin(), group.end());
}
CommonCode Group::group_seed(const GroupId &group_id) {
auto offset = TYPE_ID_OFFSET[group_id.type_id()]; // type id offset
auto index = offset + GROUP_SEEDS_INDEX[offset + group_id.unwrap()];
CommonCode GroupId::seed() const noexcept {
auto offset = TYPE_ID_OFFSET[type_id_.unwrap()]; // type id offset
auto index = offset + GROUP_SEEDS_INDEX[offset + group_id_];
return CommonCode::unsafe_create(GROUP_SEEDS[index]);
}
std::vector<CommonCode> Group::group_seeds(const TypeId &type_id) {
auto offset = GROUP_SEEDS + TYPE_ID_OFFSET[type_id.unwrap()]; // type id offset
return {offset, offset + TYPE_ID_GROUP_NUM[type_id.unwrap()]};
std::vector<CommonCode> TypeId::seeds() const noexcept {
auto offset = GROUP_SEEDS + TYPE_ID_OFFSET[type_id_]; // type id offset
return {offset, offset + TYPE_ID_GROUP_NUM[type_id_]};
}
} // namespace klotski

18
test/group/build_cases.cc

@ -29,7 +29,7 @@ const char GROUP_INFO_MD5[] = "976bf22530085210e68a6a4e67053506";
TEST(Group, all_cases) {
std::array<std::vector<CommonCode>, TYPE_ID_LIMIT> all_cases;
auto build = [&all_cases](TypeId type_id) {
auto cases = Group::all_cases(type_id); // build test data
auto cases = type_id.all_cases(); // build test data
EXPECT_EQ(cases.size(), TYPE_ID_SIZE[type_id.unwrap()]); // verify cases number
for (auto &&common_code : cases) {
EXPECT_EQ(TypeId(common_code), type_id); // verify type id
@ -59,10 +59,10 @@ TEST(Group, all_cases) {
TEST(Group, group_cases) {
auto build = [](CommonCode seed) -> std::vector<CommonCode> {
auto group_raw = Group::group_cases(seed);
auto group_raw = Group::cases(seed);
std::vector<CommonCode> group(group_raw.begin(), group_raw.end()); // convert as CommonCodes
EXPECT_EQ(seed, std::min_element(group.begin(), group.end())->unwrap()); // confirm min seed
EXPECT_EQ(group.size(), Group::group_size(seed)); // verify group size
EXPECT_EQ(group.size(), GroupId::size(seed)); // verify group size
uint32_t type_id = TypeId(seed).unwrap(); // current type id
for (auto &&elem : group) {
@ -94,7 +94,7 @@ TEST(Group, group_seeds) {
std::vector<CommonCode> all_seeds;
all_seeds.reserve(ALL_GROUP_NUM);
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) {
auto seeds = Group::group_seeds(TypeId(type_id));
auto seeds = TypeId(type_id).seeds();
for (auto &&seed : seeds) {
EXPECT_EQ(TypeId(seed).unwrap(), type_id); // verify type id of seeds
}
@ -103,7 +103,7 @@ TEST(Group, group_seeds) {
std::vector<CommonCode> sub_seeds;
sub_seeds.reserve(TYPE_ID_GROUP_NUM[type_id]);
for (uint32_t group_id = 0; group_id < TYPE_ID_GROUP_NUM[type_id]; ++group_id) {
sub_seeds.emplace_back(Group::group_seed(GroupId(type_id, group_id)));
sub_seeds.emplace_back(GroupId(type_id, group_id).seed());
}
std::sort(seeds.begin(), seeds.end());
std::sort(sub_seeds.begin(), sub_seeds.end()); // don't verify seeds order for now
@ -113,8 +113,8 @@ TEST(Group, group_seeds) {
EXPECT_EQ(all_seeds, group_seeds); // verify group seeds
auto test = [](CommonCode seed) {
EXPECT_EQ(Group::group_seed(seed), seed); // verify group seed fetch
EXPECT_EQ(Group::group_seed(seed.to_raw_code()), seed);
EXPECT_EQ(GroupId::seed(seed), seed); // verify group seed fetch
EXPECT_EQ(GroupId::seed(seed.to_raw_code()), seed);
};
auto pool = TinyPool();
for (auto &&seed : GROUP_SEEDS) { // traverse all seeds
@ -139,8 +139,8 @@ TEST(Group, build_groups) {
std::sort(group.begin(), group.end());
std::sort(groups[group_id].begin(), groups[group_id].end());
EXPECT_EQ(groups[group_id], group); // verify group data
EXPECT_EQ(group.size(), Group::group_size(GroupId(type_id, group_id))); // verify group size
EXPECT_EQ(*group.begin(), Group::group_seed(GroupId(type_id, group_id))); // verify group seed
EXPECT_EQ(group.size(), GroupId(type_id, group_id).size()); // verify group size
EXPECT_EQ(*group.begin(), GroupId(type_id, group_id).seed()); // verify group seed
for (uint32_t index = 0; index < group.size(); ++index) {
all_cases[group[index].to_short_code().unwrap()] = { // storage group info

Loading…
Cancel
Save