Browse Source

feat: mirror functions of CommonCode

master
Dnomd343 5 months ago
parent
commit
75df4e536b
  1. 27
      src/core/common_code/common_code.h
  2. 36
      src/core/common_code/internal/common_code.inl
  3. 38
      src/core/common_code/internal/mirror.cc
  4. 28
      src/core/main.cc

27
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<uint64_t> 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<CommonCode>);

36
src/core/common_code/internal/common_code.inl

@ -1,13 +1,11 @@
#pragma once
#include <bit>
#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> 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> 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> 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> 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

38
src/core/common_code/internal/mirror.cc

@ -1,23 +1,20 @@
#include <iostream>
#include <format>
#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<bool, 6> state {}; // mark emtry/half-full
std::array<bool, 5> 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();
}

28
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});

Loading…
Cancel
Save