diff --git a/src/core/common_code/common_code.h b/src/core/common_code/common_code.h index 538422d..6c6d034 100644 --- a/src/core/common_code/common_code.h +++ b/src/core/common_code/common_code.h @@ -139,6 +139,20 @@ public: // ------------------------------------------------------------------------------------- // + /// Whether the layout is vertically symmetrical. + [[nodiscard]] bool is_vertical_mirror() const; + + /// Whether the layout is horizontally symmetrical. + [[nodiscard]] bool is_horizontal_mirror() const; + + /// Calculate the vertically symmetrical klotski layout. + [[nodiscard]] CommonCode to_vertical_mirror() const; + + /// Calculate the horizontally symmetrical klotski layout. + [[nodiscard]] CommonCode to_horizontal_mirror() const; + + // ------------------------------------------------------------------------------------- // + /// Compare CommonCode with u64 value. friend constexpr auto operator==(const CommonCode &lhs, uint64_t rhs); friend constexpr auto operator<=>(const CommonCode &lhs, uint64_t rhs); @@ -149,8 +163,6 @@ public: // ------------------------------------------------------------------------------------- // - static bool is_mirror(uint64_t common_code); - private: uint64_t code_; @@ -166,6 +178,17 @@ private: static std::optional string_decode(std::string_view common_code); // ------------------------------------------------------------------------------------- // + + /// Check the horizontally symmetrical. + static bool check_mirror(uint64_t common_code); + + /// Get the vertically symmetrical layout. + static uint64_t get_vertical_mirror(uint64_t common_code); + + /// Get the horizontally symmetrical layout. + static uint64_t get_horizontal_mirror(uint64_t common_code); + + // ------------------------------------------------------------------------------------- // }; static_assert(std::is_standard_layout_v); diff --git a/src/core/common_code/internal/common_code.inl b/src/core/common_code/internal/common_code.inl index f6b70ee..3fb3b25 100644 --- a/src/core/common_code/internal/common_code.inl +++ b/src/core/common_code/internal/common_code.inl @@ -1,13 +1,11 @@ #pragma once -#include - #include "raw_code/raw_code.h" #include "short_code/short_code.h" namespace klotski::codec { -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // inline CommonCode::CommonCode(const RawCode raw_code) { code_ = raw_code.to_common_code().code_; @@ -28,7 +26,7 @@ inline std::optional CommonCode::create(const uint64_t common_code) return unsafe_create(common_code); } -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // inline CommonCode::operator uint64_t() const { return code_; @@ -41,7 +39,7 @@ inline std::ostream& operator<<(std::ostream &out, const CommonCode self) { } #endif -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // inline uint64_t CommonCode::unwrap() const { return code_; @@ -62,13 +60,13 @@ inline std::string CommonCode::to_string(const bool shorten) const { return string_encode_shorten(code_); // without trailing zero } -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // inline std::optional CommonCode::from_string(const std::string_view common_code) { return string_decode(common_code).transform(unsafe_create); } -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // inline CommonCode CommonCode::from_raw_code(const RawCode raw_code) { return raw_code.to_common_code(); @@ -81,7 +79,7 @@ inline std::optional CommonCode::from_raw_code(const uint64_t raw_co return RawCode::create(raw_code).transform(convert); } -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // inline CommonCode CommonCode::from_short_code(const ShortCode short_code) { return short_code.to_common_code(); @@ -101,7 +99,25 @@ inline std::optional CommonCode::from_short_code(const std::string_v return ShortCode::from_string(short_code).transform(convert); } -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // + +inline bool CommonCode::is_vertical_mirror() const { + return false; +} + +inline bool CommonCode::is_horizontal_mirror() const { + return check_mirror(code_); +} + +inline CommonCode CommonCode::to_vertical_mirror() const { + return unsafe_create(get_vertical_mirror(code_)); +} + +inline CommonCode CommonCode::to_horizontal_mirror() const { + return unsafe_create(get_horizontal_mirror(code_)); +} + +// ----------------------------------------------------------------------------------------- // constexpr auto operator==(const CommonCode &lhs, const uint64_t rhs) { return lhs.code_ == rhs; @@ -119,6 +135,6 @@ constexpr auto operator<=>(const CommonCode &lhs, const CommonCode &rhs) { return lhs.code_ <=> rhs.code_; } -// ------------------------------------------------------------------------------------- // +// ----------------------------------------------------------------------------------------- // } // namespace klotski::codec diff --git a/src/core/common_code/internal/mirror.cc b/src/core/common_code/internal/mirror.cc index 03a350d..1e8b338 100644 --- a/src/core/common_code/internal/mirror.cc +++ b/src/core/common_code/internal/mirror.cc @@ -1,23 +1,20 @@ -#include #include #include "common_code/common_code.h" using klotski::codec::CommonCode; -bool CommonCode::is_mirror(uint64_t common_code) { +// TODO: performance optimization. +bool CommonCode::check_mirror(uint64_t common_code) { int head = common_code >> 32; uint32_t ranges = range_reverse(common_code); - // std::cout << "head = " << head << std::endl; - // std::cout << "ranges = " << std::format("{:08X}", ranges) << std::endl; - if (head % 4 != 1) { return false; } - std::array state {}; // mark emtry/half-full + std::array state {}; // mark emtry/half-full if (head == 1) { state.at(0) = true; @@ -38,16 +35,10 @@ bool CommonCode::is_mirror(uint64_t common_code) { while (1 == 1) { if (working_line > 4) { - // std::cout << "reach end line" << std::endl; break; } - // std::cout << std::endl; - // std::cout << "working_line: " << working_line << std::endl; - // std::cout << "state: " << std::format("{}", state) << std::endl; - if (!state.at(working_line)) { // empty line - // std::cout << "empty working line" << std::endl; /// simple single line bool is_single_line = false; @@ -68,7 +59,6 @@ bool CommonCode::is_mirror(uint64_t common_code) { } } if (is_single_line) { - // std::cout << "simple single line" << std::endl; ++working_line; // next line continue; } @@ -86,7 +76,6 @@ bool CommonCode::is_mirror(uint64_t common_code) { } } if (is_half_double_line) { - // std::cout << "half double line" << std::endl; if (state.at(working_line + 1)) { working_line += 2; // next 2 lines } else { @@ -98,19 +87,15 @@ bool CommonCode::is_mirror(uint64_t common_code) { /// full-double line if ((ranges & 0b11111111) == 0b10101010) { - // std::cout << "full double line" << std::endl; ranges >>= 8; working_line += 2; continue; } - // std::cout << "not mirror layout" << std::endl; return false; } else { // half-full line - // std::cout << "half-full working line" << std::endl; - /// simple single line bool is_simple_line = false; if ((ranges & 0b11) == 0b01) { @@ -125,14 +110,12 @@ bool CommonCode::is_mirror(uint64_t common_code) { } } if (is_simple_line) { - // std::cout << "simple single line" << std::endl; ++working_line; continue; } /// half-double line if ((ranges & 0b1111) == 0b1010) { - // std::cout << "half double line" << std::endl; ranges >>= 4; if (state.at(working_line + 1)) { working_line += 2; // next 2 lines @@ -143,12 +126,21 @@ bool CommonCode::is_mirror(uint64_t common_code) { continue; } - // std::cout << "not mirror layout" << std::endl; return false; - } - } return true; } + +// TODO: temporarily use RawCode conversion. +uint64_t CommonCode::get_vertical_mirror(uint64_t common_code) { + auto raw_code = unsafe_create(common_code).to_raw_code(); + return raw_code.to_vertical_mirror().to_common_code().unwrap(); +} + +// TODO: temporarily use RawCode conversion. +uint64_t CommonCode::get_horizontal_mirror(uint64_t common_code) { + auto raw_code = unsafe_create(common_code).to_raw_code(); + return raw_code.to_horizontal_mirror().to_common_code().unwrap(); +} diff --git a/src/core/main.cc b/src/core/main.cc index ac46434..f6861dc 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -49,18 +49,36 @@ int main() { // auto raw_code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); // std::cout << raw_code.is_horizontal_mirror() << std::endl; - // for (auto common_code : AllCases::instance().fetch().codes()) { - // auto raw_code = common_code.to_raw_code(); - // + for (auto common_code : AllCases::instance().fetch().codes()) { + auto raw_code = common_code.to_raw_code(); + // bool r1 = raw_code.is_horizontal_mirror(); - // bool r2 = CommonCode::is_mirror(common_code.unwrap()); + // bool r2 = common_code.is_horizontal_mirror(); // // if (r1 != r2) { // std::cout << "found invalid" << std::endl; // std::cout << common_code << std::endl; // break; // } - // } + // + // // if (raw_code.is_vertical_mirror()) { + // // std::cout << "found invalid" << std::endl; + // // break; + // // } + + // auto rr = raw_code.to_vertical_mirror(); + // auto cc = common_code.to_vertical_mirror(); + auto rr = raw_code.to_horizontal_mirror(); + auto cc = common_code.to_horizontal_mirror(); + if (cc.to_raw_code() != rr) { + std::cout << "found invalid" << std::endl; + std::cout << common_code << std::endl; + break; + } + + } + + // GroupCases::from_info_t({169, 1, 7472});