diff --git a/src/klotski_core/group/build_cases.cc b/src/klotski_core/group/build_cases.cc index d9c2a72..365a649 100644 --- a/src/klotski_core/group/build_cases.cc +++ b/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 Group::group_cases(const CommonCode &common_code) { - return group_cases(common_code.to_raw_code()); +std::vector Group::cases(const CommonCode &common_code) noexcept { + return cases(common_code.to_raw_code()); } std::vector 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 Group::all_cases(const TypeId &type_id) { +std::vector TypeId::all_cases() const noexcept { std::vector 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 Group::all_cases(const TypeId &type_id) { } std::vector 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 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 cache({raw_code.unwrap()}); absl::flat_hash_map cases; // 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 Group::group_cases(const RawCode &raw_code) { +std::vector Group::cases(const RawCode &raw_code) noexcept { std::queue cache({raw_code.unwrap()}); absl::flat_hash_map cases; // cases.reserve(Group::group_max_size(raw_code)); @@ -118,11 +118,11 @@ std::vector Group::group_cases(const RawCode &raw_code) { } std::vector> Group::build_groups(const TypeId &type_id) { - auto all_cases = Group::all_cases(type_id); + auto all_cases = type_id.all_cases(); std::vector> 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> 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 diff --git a/src/klotski_core/group/group.h b/src/klotski_core/group/group.h index 84614c4..77bbf0d 100644 --- a/src/klotski_core/group/group.h +++ b/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 seeds() const noexcept; + + /// Search for all cases of the specified type_id. + std::vector 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 group_seeds(const TypeId &type_id); - -/// --------------------------------- cases expansion --------------------------------- - - /// Search for all cases of the specified type_id. - static std::vector all_cases(const TypeId &type_id); - /// Search for all derivatives that a case can produce. - static std::vector group_cases(const RawCode &raw_code); - static std::vector group_cases(const CommonCode &common_code); + static std::vector cases(const RawCode &raw_code) noexcept; + static std::vector cases(const CommonCode &common_code) noexcept; + + /// Calculate the specified group in the specified group_id. + static std::vector build_group(const GroupId &group_id); /// Calculate all groups in the specified type_id. static std::vector> build_groups(const TypeId &type_id); - /// Calculate the specified group using type_id and group_id. - static std::vector build_group(const GroupId &group_id); - /// ----------------------------------- group info ------------------------------------ struct group_info_t { diff --git a/src/klotski_core/group/group_info.cc b/src/klotski_core/group/group_info.cc index 57a6860..07807d4 100644 --- a/src/klotski_core/group/group_info.cc +++ b/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 g(group.begin(), group.end()); auto seed = std::min_element(g.begin(), g.end()); std::cout << "seed: " << *seed << std::endl; diff --git a/src/klotski_core/group/seeds.cc b/src/klotski_core/group/seeds.cc index edb2830..8a1d783 100644 --- a/src/klotski_core/group/seeds.cc +++ b/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 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 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 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 diff --git a/test/group/build_cases.cc b/test/group/build_cases.cc index ded1637..7b8628d 100644 --- a/test/group/build_cases.cc +++ b/test/group/build_cases.cc @@ -29,7 +29,7 @@ const char GROUP_INFO_MD5[] = "976bf22530085210e68a6a4e67053506"; TEST(Group, all_cases) { std::array, 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 { - auto group_raw = Group::group_cases(seed); + auto group_raw = Group::cases(seed); std::vector 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 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 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