Browse Source

feat: next group theory

legacy
Dnomd343 2 months ago
parent
commit
6fdb086ffd
  1. 1
      src/core/CMakeLists.txt
  2. 67
      src/core/group/group.h
  3. 19
      src/core/group/internal/constant/group_pro.h
  4. 18
      src/core/group/internal/constant/group_union.h
  5. 38
      src/core/group/internal/group_pro.cc
  6. 111
      src/core/group/internal/group_pro.inl
  7. 33
      src/core/group/internal/group_union.inl
  8. 31
      src/core/main.cc

1
src/core/CMakeLists.txt

@ -25,6 +25,7 @@ set(KLOTSKI_CORE_SRC
group/internal/group_union.cc
group/internal/group.cc
group/internal/group_pro.cc
group/internal/group_cases.cc
ranges/internal/spawn.cc

67
src/core/group/group.h

@ -79,6 +79,7 @@ typedef std::vector<codec::RawCode> RawCodes;
typedef std::vector<codec::CommonCode> CommonCodes;
class Group;
class GroupPro;
// TODO: add constexpr
class GroupUnion {
@ -107,6 +108,13 @@ public:
/// Get the upper limit of the group size.
[[nodiscard]] constexpr uint32_t max_group_size() const;
// ------------------------------------------------------------------------------------- //
/// TODO: new interface
[[nodiscard]] constexpr uint32_t pattern_num() const;
[[nodiscard]] std::vector<GroupPro> groups_pro() const;
// ------------------------------------------------------------------------------------- //
/// Get all cases under the current type id.
@ -145,8 +153,65 @@ private:
// ------------------------------------------------------------------------------------- //
};
// TODO: add `==` and `std::hash`
// TODO: add debug output
class GroupPro {
public:
GroupPro() = delete;
enum class MirrorType {
FullMirror = 0,
HorizontalMirror = 1,
CentroMirror = 2,
VerticalMirror = 3,
NonMirror = 4,
};
// NOTE: using enum `MirrorTowards`
static GroupPro unsafe_create(uint32_t type_id, uint32_t pattern_id, uint32_t mirror_toward) {
return {type_id, pattern_id, mirror_toward};
}
[[nodiscard]] constexpr uint32_t type_id() const {
return type_id_;
}
[[nodiscard]] constexpr uint32_t pattern_id() const {
return pattern_id_;
}
[[nodiscard]] constexpr uint32_t mirror_toward() const {
return mirror_toward_;
}
[[nodiscard]] constexpr uint32_t size() const;
[[nodiscard]] constexpr MirrorType mirror_type() const;
[[nodiscard]] constexpr bool is_vertical_mirror() const;
[[nodiscard]] constexpr bool is_horizontal_mirror() const;
[[nodiscard]] constexpr GroupPro to_vertical_mirror() const;
[[nodiscard]] constexpr GroupPro to_horizontal_mirror() const;
RangesUnion cases() const;
private:
uint32_t type_id_;
uint32_t pattern_id_;
uint32_t mirror_toward_;
GroupPro(uint32_t type_id, uint32_t pattern_id, uint32_t mirror_toward) {
type_id_ = type_id;
pattern_id_ = pattern_id;
mirror_toward_ = mirror_toward;
}
[[nodiscard]] constexpr uint32_t flat_id() const;
};
class Group {
public:
Group() = delete;
@ -281,3 +346,5 @@ public:
#include "internal/group_union.inl"
#include "internal/group_cases.inl"
#include "internal/group.inl"
#include "internal/group_pro.inl"

19
src/core/group/internal/constant/group_pro.h

File diff suppressed because one or more lines are too long

18
src/core/group/internal/constant/group_union.h

@ -25,6 +25,24 @@ constexpr auto GROUP_NUM = std::to_array<uint16_t>({
constexpr auto GROUP_OFFSET = to_offset<uint16_t, 203>(GROUP_NUM);
constexpr auto PATTERN_NUM = std::to_array<uint16_t>({
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 4 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 2 , 22 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 6 , 36 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 5 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 6 , 70 , 1 , 1 , 1 , 1 , 1 , 1 , 3 , 37 , 211, 1 , 1 , 1 , 1 ,
1 , 1 , 5 , 25 , 131, 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 24 , 1 , 1 ,
1 , 1 , 1 , 17 , 150, 1 , 1 , 1 , 1 , 6 , 89 , 436, 1 , 1 , 1 , 3 ,
22, 122, 589, 1 , 1 , 1 , 2 , 9 , 42 , 265, 1 , 1 , 1 , 1 , 1 , 3 ,
41, 1 , 1 , 1 , 15 , 129, 1 , 1 , 4 , 82 , 433, 2 , 3 , 27 , 160, 658,
1 , 5 , 24 , 123, 665, 1 , 1 , 4 , 20 , 230, 1 , 1 , 1 , 1 , 21 , 1 ,
1 , 36 , 4 , 32 , 148, 8 , 48, 276, 9 , 53 , 295, 4 , 46, 306, 3 , 5 ,
58, 2 , 6 , 15 , 1 , 11 , 12, 31 , 24 , 19 , 6 ,
});
const auto PATTERN_OFFSET = to_offset<uint16_t, 203>(PATTERN_NUM);
/// The maximum Group size in each GroupUnion.
constexpr auto MAX_GROUP_SIZE = std::to_array<uint32_t>({
12 , 192 , 1440 , 6720 , 21840 , 52416 , 96096 , 137280, 154440, 137280, 96096 , 52416 ,

38
src/core/group/internal/group_pro.cc

@ -0,0 +1,38 @@
#include <algorithm>
#include "group/group.h"
using klotski::cases::GroupPro;
using klotski::codec::CommonCode;
using klotski::cases::RangesUnion;
using klotski::cases::GROUP_PRO_SEED;
RangesUnion GroupPro::cases() const {
auto seed = CommonCode::unsafe_create(GROUP_PRO_SEED[flat_id()]);
// NOTE: convert as RawCode directly
if (mirror_toward_ == 1) {
seed = seed.to_horizontal_mirror();
} else if (mirror_toward_ == 2) {
seed = seed.to_vertical_mirror();
} else if (mirror_toward_ == 3) {
// NOTE: avoid multi convert
seed = seed.to_vertical_mirror().to_horizontal_mirror();
}
auto codes = Group::extend(seed.to_raw_code(), size());
RangesUnion data;
for (auto raw_code : codes) {
auto common_code = raw_code.to_common_code().unwrap();
data[common_code >> 32].emplace_back(static_cast<uint32_t>(common_code));
}
for (int head = 0; head < 16; ++head) {
std::stable_sort(data[head].begin(), data[head].end());
}
return data;
}

111
src/core/group/internal/group_pro.inl

@ -0,0 +1,111 @@
#pragma once
#include "constant/group_pro.h"
namespace klotski::cases {
constexpr uint32_t GroupPro::flat_id() const {
return PATTERN_OFFSET[type_id_] + pattern_id_;
}
constexpr uint32_t GroupPro::size() const {
return GROUP_PRO_SIZE[flat_id()];
}
constexpr GroupPro::MirrorType GroupPro::mirror_type() const {
switch (GROUP_PRO_TYPE[flat_id()]) {
case 0:
return MirrorType::FullMirror;
case 1:
return MirrorType::HorizontalMirror;
case 2:
return MirrorType::CentroMirror;
case 3:
return MirrorType::VerticalMirror;
case 4:
return MirrorType::NonMirror;
}
}
constexpr bool GroupPro::is_vertical_mirror() const {
switch (mirror_type()) {
case MirrorType::FullMirror:
return true;
case MirrorType::HorizontalMirror:
return false;
case MirrorType::CentroMirror:
return false;
case MirrorType::VerticalMirror:
return true;
case MirrorType::NonMirror:
return false;
}
}
constexpr bool GroupPro::is_horizontal_mirror() const {
switch (mirror_type()) {
case MirrorType::FullMirror:
return true;
case MirrorType::HorizontalMirror:
return true;
case MirrorType::CentroMirror:
return false;
case MirrorType::VerticalMirror:
return false;
case MirrorType::NonMirror:
return false;
}
}
constexpr GroupPro GroupPro::to_vertical_mirror() const {
switch (mirror_type()) {
case MirrorType::FullMirror:
return *this;
case MirrorType::HorizontalMirror:
if (mirror_toward_ == 0) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 2);
}
return GroupPro::unsafe_create(type_id_, pattern_id_, 0);
case MirrorType::CentroMirror:
if (mirror_toward_ == 0) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 1);
}
return GroupPro::unsafe_create(type_id_, pattern_id_, 0);
case MirrorType::VerticalMirror:
return *this;
case MirrorType::NonMirror:
if (mirror_toward_ == 0) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 2);
} else if (mirror_toward_ == 1) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 3);
} else if (mirror_toward_ == 2) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 0);
}
return GroupPro::unsafe_create(type_id_, pattern_id_, 1);
}
}
constexpr GroupPro GroupPro::to_horizontal_mirror() const {
switch (mirror_type()) {
case MirrorType::FullMirror:
case MirrorType::HorizontalMirror:
return *this;
case MirrorType::CentroMirror:
case MirrorType::VerticalMirror:
if (mirror_toward_ == 0) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 1);
}
return GroupPro::unsafe_create(type_id_, pattern_id_, 0);
case MirrorType::NonMirror:
if (mirror_toward_ == 0) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 2);
} else if (mirror_toward_ == 1) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 3);
} else if (mirror_toward_ == 2) {
return GroupPro::unsafe_create(type_id_, pattern_id_, 0);
}
return GroupPro::unsafe_create(type_id_, pattern_id_, 1);
}
}
} // namespace klotski::cases

33
src/core/group/internal/group_union.inl

@ -53,6 +53,39 @@ inline std::optional<Group> GroupUnion::group(const uint32_t group_id) const {
return std::nullopt;
}
// ----------------------------------------------------------------------------------------- //
// TODO: new interface
constexpr uint32_t GroupUnion::pattern_num() const {
return PATTERN_NUM[type_id_];
}
inline std::vector<GroupPro> GroupUnion::groups_pro() const {
std::vector<GroupPro> groups;
groups.reserve(group_num());
for (uint32_t pattern_id = 0; pattern_id < pattern_num(); ++pattern_id) {
auto group = GroupPro::unsafe_create(type_id_, pattern_id, 0);
groups.emplace_back(group);
switch (group.mirror_type()) {
case GroupPro::MirrorType::FullMirror:
continue;
case GroupPro::MirrorType::HorizontalMirror:
groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 2));
break;
case GroupPro::MirrorType::CentroMirror:
case GroupPro::MirrorType::VerticalMirror:
groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 1));
break;
case GroupPro::MirrorType::NonMirror:
groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 1));
groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 2));
groups.emplace_back(GroupPro::unsafe_create(type_id_, pattern_id, 3));
break;
}
}
return groups;
}
// ----------------------------------------------------------------------------------------- //
inline GroupUnion GroupUnion::from_raw_code(const codec::RawCode raw_code) {

31
src/core/main.cc

@ -27,6 +27,7 @@ using klotski::codec::CommonCode;
using klotski::cases::GroupUnion;
using klotski::cases::Group;
using klotski::cases::GroupPro;
using klotski::cases::GroupCases;
using klotski::cases::GroupUnion;
@ -52,10 +53,34 @@ int main() {
// std::cout << GroupCases::fast_obtain(CommonCode::unsafe_create(0x1A9BF0C00)) << std::endl;
// std::cout << GroupCases::fast_obtain(CommonCode::unsafe_create(0x4FEA13400)) << std::endl;
auto group = Group::unsafe_create(123, 1446);
auto gu = GroupUnion::unsafe_create(169);
std::cout << gu.pattern_num() << std::endl;
std::cout << group.to_horizontal_mirror().group_id() << std::endl;
std::cout << group.to_vertical_mirror().group_id() << std::endl;
std::cout << gu.group_num() << std::endl;
std::cout << gu.groups_pro().size() << std::endl;
const auto g = gu.groups_pro()[1];
std::cout << std::format("{}-{}-{}\n", g.type_id(), g.pattern_id(), g.mirror_toward());
const auto codes = g.cases().codes();
std::cout << codes.size() << std::endl;
for (const auto code : codes) {
if (code == 0x1A9BF0C00) {
std::cout << "get it" << std::endl;
}
}
std::cout << g.is_vertical_mirror() << std::endl;
std::cout << g.is_horizontal_mirror() << std::endl;
auto g1 = g.to_vertical_mirror();
std::cout << std::format("{}-{}-{}\n", g1.type_id(), g1.pattern_id(), g1.mirror_toward());
auto g2 = g.to_horizontal_mirror();
std::cout << std::format("{}-{}-{}\n", g2.type_id(), g2.pattern_id(), g2.mirror_toward());
// auto gp = GroupPro::unsafe_create(169, 0, 0);
// std::cout << gp.size() << std::endl;
// std::cout << (int)gp.mirror_type() << std::endl;
std::cerr << std::chrono::system_clock::now() - start << std::endl;

Loading…
Cancel
Save