Browse Source

update: enhance RawCode module

master
Dnomd343 1 year ago
parent
commit
eb1967dec0
  1. 6
      src/klotski_core/raw_code/convert.cc
  2. 34
      src/klotski_core/raw_code/mirror.cc
  3. 87
      src/klotski_core/raw_code/raw_code.cc
  4. 152
      src/klotski_core/raw_code/raw_code.h

6
src/klotski_core/raw_code/convert.cc

@ -8,17 +8,17 @@ using klotski::RawCodeException;
/// -------------------------- RawCode to CommonCode --------------------------
CommonCode RawCode::to_common_code() const noexcept {
return CommonCode::unsafe_create(RawCode::compact(code));
return CommonCode::unsafe_create(RawCode::compact(code_));
}
/// -------------------------- CommonCode to RawCode --------------------------
RawCode::RawCode(CommonCode &&common_code) noexcept {
code = RawCode::extract(common_code.unwrap()); // convert from common code
code_ = RawCode::extract(common_code.unwrap()); // convert from common code
}
RawCode::RawCode(const CommonCode &common_code) noexcept {
code = RawCode::extract(common_code.unwrap()); // convert from common code
code_ = RawCode::extract(common_code.unwrap()); // convert from common code
}
RawCode RawCode::from_common_code(uint64_t common_code) {

34
src/klotski_core/raw_code/mirror.cc

@ -6,37 +6,37 @@ using klotski::RawCode;
/// ----------------------------- Mirror Convert ------------------------------
RawCode RawCode::to_vertical_mirror() const noexcept {
return RawCode::unsafe_create(vertical_mirror(code));
return RawCode::unsafe_create(get_vertical_mirror(code_));
}
RawCode RawCode::to_horizontal_mirror() const noexcept {
return RawCode::unsafe_create(horizontal_mirror(code));
return RawCode::unsafe_create(get_horizontal_mirror(code_));
}
/// ------------------------------ Mirror Check -------------------------------
bool RawCode::is_vertical_mirror() const noexcept {
return vertical_mirror_check(code);
return check_vertical_mirror(code_);
}
bool RawCode::is_horizontal_mirror() const noexcept {
return horizontal_mirror_check(code);
return check_horizontal_mirror(code_);
}
bool RawCode::is_vertical_mirror(RawCode &&raw_code) const noexcept {
return raw_code.unwrap() == vertical_mirror(code);
return raw_code.unwrap() == get_vertical_mirror(code_);
}
bool RawCode::is_horizontal_mirror(RawCode &&raw_code) const noexcept {
return raw_code.unwrap() == horizontal_mirror(code);
return raw_code.unwrap() == get_horizontal_mirror(code_);
}
bool RawCode::is_vertical_mirror(const RawCode &raw_code) const noexcept {
return raw_code.unwrap() == vertical_mirror(code);
return raw_code.unwrap() == get_vertical_mirror(code_);
}
bool RawCode::is_horizontal_mirror(const RawCode &raw_code) const noexcept {
return raw_code.unwrap() == horizontal_mirror(code);
return raw_code.unwrap() == get_horizontal_mirror(code_);
}
/// ----------------------------- Basic Functions -----------------------------
@ -64,14 +64,14 @@ constexpr uint64_t MASK_MIRROR_V3 = 0x0'000'000'FFF'000'000;
inline void vertical_fill(uint64_t &raw_code) {
uint64_t mask = 0;
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bits
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) {
case B_2x1:
case B_2x2:
mask |= (uint64_t)0b111 << (addr + 12); // generate fill mask
}
}
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bits
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code | mask) >> addr & 0b111) {
case B_2x1:
raw_code &= ~(uint64_t(~B_2x1 & 0b111) << (addr + 12)); // fill vertical mirror
@ -84,7 +84,7 @@ inline void vertical_fill(uint64_t &raw_code) {
}
inline void horizontal_fill(uint64_t &raw_code) {
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bits
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) {
case B_1x2:
raw_code &= ~(uint64_t(~B_1x2 & 0b111) << (addr + 3)); // fill horizontal mirror
@ -99,7 +99,7 @@ inline void horizontal_fill(uint64_t &raw_code) {
}
inline void vertical_clear(uint64_t &raw_code) {
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bits
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) {
case B_2x1:
case B_2x2:
@ -109,7 +109,7 @@ inline void vertical_clear(uint64_t &raw_code) {
}
inline void horizontal_clear(uint64_t &raw_code) {
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bits
for (int addr = 0; addr < 60; addr += 3) { // traverse every 3-bit
switch ((raw_code >> addr) & 0b111) {
case B_1x2:
case B_2x2:
@ -118,7 +118,7 @@ inline void horizontal_clear(uint64_t &raw_code) {
}
}
uint64_t RawCode::vertical_mirror(uint64_t raw_code) noexcept {
uint64_t RawCode::get_vertical_mirror(uint64_t raw_code) noexcept {
vertical_fill(raw_code);
raw_code = (raw_code & MASK_MIRROR_V3)
| ((raw_code >> 48) & MASK_MIRROR_V1) | ((raw_code >> 24) & MASK_MIRROR_V2)
@ -127,7 +127,7 @@ uint64_t RawCode::vertical_mirror(uint64_t raw_code) noexcept {
return raw_code;
}
uint64_t RawCode::horizontal_mirror(uint64_t raw_code) noexcept {
uint64_t RawCode::get_horizontal_mirror(uint64_t raw_code) noexcept {
horizontal_fill(raw_code);
raw_code = ((raw_code >> 9) & MASK_MIRROR_H1) | ((raw_code >> 3) & MASK_MIRROR_H2)
| ((raw_code & MASK_MIRROR_H2) << 3) | ((raw_code & MASK_MIRROR_H1) << 9); // flip raw code
@ -135,13 +135,13 @@ uint64_t RawCode::horizontal_mirror(uint64_t raw_code) noexcept {
return raw_code;
}
bool RawCode::vertical_mirror_check(uint64_t raw_code) noexcept {
bool RawCode::check_vertical_mirror(uint64_t raw_code) noexcept {
vertical_fill(raw_code);
return !(MASK_MIRROR_V1 & ((raw_code >> 48) ^ raw_code))
&& !(MASK_MIRROR_V2 & ((raw_code >> 24) ^ raw_code));
}
bool RawCode::horizontal_mirror_check(uint64_t raw_code) noexcept {
bool RawCode::check_horizontal_mirror(uint64_t raw_code) noexcept {
horizontal_fill(raw_code);
return !(MASK_MIRROR_H1 & ((raw_code >> 9) ^ raw_code))
&& !(MASK_MIRROR_H2 & ((raw_code >> 3) ^ raw_code));

87
src/klotski_core/raw_code/raw_code.cc

@ -1,70 +1,42 @@
#include "common.h"
#include "raw_code.h"
using klotski::RawCode;
namespace std {
template<>
struct hash<klotski::RawCode> {
std::size_t operator()(const klotski::RawCode &c) const {
return std::hash<uint64_t>()(c.unwrap());
}
};
template<>
struct equal_to<klotski::RawCode> {
bool operator()(const klotski::RawCode &c1, const klotski::RawCode &c2) const {
return c1.unwrap() == c2.unwrap();
}
};
}
namespace klotski {
bool RawCode::operator==(const RawCode &raw_code) const noexcept {
return this->code == raw_code.code;
}
bool RawCode::operator!=(const RawCode &raw_code) const noexcept {
return this->code != raw_code.code;
}
std::ostream& operator<<(std::ostream &out, const RawCode &self) {
char code[16];
char dump_map[] = {
/// 0x0 1x2 2x1 1x1 2x2 b101 b110 fill
'.', '~', '|', '*', '@', '?', '?', '+'
};
sprintf(code, "%015lX", self.code); // code length -> 15
out << code << '\n';
for (int addr = 0; addr < 60; addr += 3) {
out << dump_map[(self.code >> addr) & 0b111];
out << " " << &"\n"[(addr & 0b11) != 0b01];
}
return out;
}
bool RawCode::valid() const noexcept {
return RawCode::check(code_);
}
namespace klotski {
bool RawCode::valid() const noexcept {
return RawCode::check(code);
}
RawCode RawCode::create(uint64_t raw_code) {
return RawCode(raw_code);
}
RawCode RawCode::create(uint64_t raw_code) {
return RawCode(raw_code);
}
RawCode RawCode::unsafe_create(uint64_t raw_code) noexcept { // create without check
auto tmp = RawCode(); // init directly
tmp.code_ = raw_code;
return tmp;
}
RawCode RawCode::unsafe_create(uint64_t raw_code) noexcept { // create without check
auto tmp = RawCode(); // init directly
tmp.code = raw_code;
return tmp;
RawCode::RawCode(uint64_t raw_code) {
if (!RawCode::check(raw_code)) { // check input raw code
throw klotski::RawCodeException("raw code invalid");
}
code_ = raw_code;
}
RawCode::RawCode(uint64_t raw_code) {
if (!RawCode::check(raw_code)) { // check input raw code
throw klotski::RawCodeException("raw code invalid");
}
code = raw_code;
std::ostream& operator<<(std::ostream &out, const RawCode &self) {
char code[16];
char dump_map[] = {
/// 0x0 1x2 2x1 1x1 2x2 b101 b110 fill
'.', '~', '|', '*', '@', '?', '?', '+'
};
sprintf(code, "%015lX", self.code_); // code length -> 15
out << code << '\n';
for (int addr = 0; addr < 60; addr += 3) {
out << dump_map[(self.code_ >> addr) & 0b111];
out << " " << &"\n"[(addr & 0b11) != 0b01];
}
return out;
}
bool RawCode::check(uint64_t raw_code) noexcept { // check whether raw code is valid
@ -78,10 +50,9 @@ bool RawCode::check(uint64_t raw_code) noexcept { // check whether raw code is v
constexpr uint64_t MASK_2x1 = MASK_1x1 << 12;
constexpr uint64_t MASK_2x2 = MASK_1x1 << 3 | MASK_1x1 << 12 | MASK_1x1 << 15;
if (raw_code >> 60) {
return false; // high 4-bits must be zero
return false; // high 4-bit must be zero
}
/// check each block
int head_num = 0, space_num = 0; // statistics for space and 2x2 number
for (int addr = 0; addr < 20; ++addr, raw_code >>= 3) {
switch (raw_code & 0b111) {
@ -116,3 +87,5 @@ bool RawCode::check(uint64_t raw_code) noexcept { // check whether raw code is v
}
return head_num == 1 && space_num >= 2; // one head and at least 2 space
}
} // namespace klotski

152
src/klotski_core/raw_code/raw_code.h

@ -1,14 +1,14 @@
#pragma once
/// RawCode is an uncompressed coding scheme, which is used for program calculation. It
/// encodes a `5x4` chessboard as `0 ~ 19`, and uses 3-bits to represent each position,
/// occupying a total of 60-bits, and stored in a `uint64_t` variable. Among them, the
/// upper 4-bits are reserved and filled with `0`.
/// encodes a `5x4` chessboard as `0 ~ 19`, and uses 3-bit to represent each position,
/// occupying a total of 60-bit, and stored in a `uint64_t` variable. Among them, the
/// upper 4-bit are reserved and filled with `0`.
///
/// 00 01 02 03
/// 04 05 06 07 fill 20-slots
/// 04 05 06 07 fill 20 slots
/// 08 09 10 11 0000 (19) (18) (17) (16) ... (03) (02) (01) (00)
/// 12 13 14 15 (4b) + (3b) * 20 => 64-bits
/// 12 13 14 15 (4b) + (3b) * 20 => 64-bit
/// 16 17 18 19
///
/// Eg1:
@ -44,73 +44,75 @@
#include "common_code.h"
namespace klotski {
class CommonCode; // import for convert interface
class RawCodeException : public std::runtime_error {
public:
RawCodeException() : std::runtime_error("invalid raw code") {}
explicit RawCodeException(const std::string &msg) : std::runtime_error(msg) {}
~RawCodeException() noexcept override = default;
};
class RawCode {
uint64_t code;
RawCode() = default; // unsafe initialize
static inline uint64_t compact(uint64_t raw_code) noexcept; // raw code -> common code
static inline uint64_t extract(uint64_t common_code) noexcept; // common code -> raw code
static inline uint64_t vertical_mirror(uint64_t raw_code) noexcept; // to vertical mirror
static inline uint64_t horizontal_mirror(uint64_t raw_code) noexcept; // to horizontal mirror
static inline bool vertical_mirror_check(uint64_t raw_code) noexcept; // check vertical mirror
static inline bool horizontal_mirror_check(uint64_t raw_code) noexcept; // check horizontal mirror
public:
/// RawCode validity check
bool valid() const noexcept;
static bool check(uint64_t raw_code) noexcept;
/// Operators of RawCode
bool operator==(const RawCode &raw_code) const noexcept;
bool operator!=(const RawCode &raw_code) const noexcept;
constexpr explicit operator uint64_t() const noexcept { return code; }
friend std::ostream& operator<<(std::ostream &out, const RawCode &self);
/// Export functions
CommonCode to_common_code() const noexcept;
constexpr uint64_t unwrap() const noexcept { return code; }
/// RawCode constructors
explicit RawCode(uint64_t raw_code);
explicit RawCode(CommonCode &&common_code) noexcept;
explicit RawCode(const CommonCode &common_code) noexcept;
/// Static initialization
static RawCode create(uint64_t raw_code);
static RawCode unsafe_create(uint64_t raw_code) noexcept;
static RawCode from_common_code(uint64_t common_code);
static RawCode from_common_code(CommonCode &&common_code) noexcept;
static RawCode from_common_code(std::string &&common_code);
static RawCode from_common_code(const CommonCode &common_code) noexcept;
static RawCode from_common_code(const std::string &common_code);
/// Mirror functions
RawCode to_vertical_mirror() const noexcept;
RawCode to_horizontal_mirror() const noexcept;
bool is_vertical_mirror() const noexcept; // whether vertically symmetrical
bool is_horizontal_mirror() const noexcept; // whether horizontally symmetrical
bool is_vertical_mirror(RawCode &&raw_code) const noexcept; // whether vertically symmetric to another
bool is_vertical_mirror(const RawCode &raw_code) const noexcept;
bool is_horizontal_mirror(RawCode &&raw_code) const noexcept; // whether horizontally symmetric to another
bool is_horizontal_mirror(const RawCode &raw_code) const noexcept;
};
inline bool operator==(uint64_t r1, const RawCode &r2) noexcept { return r1 == r2.unwrap(); }
inline bool operator!=(uint64_t r1, const RawCode &r2) noexcept { return r1 != r2.unwrap(); }
inline bool operator==(const RawCode &r1, uint64_t r2) noexcept { return r1.unwrap() == r2; }
inline bool operator!=(const RawCode &r1, uint64_t r2) noexcept { return r1.unwrap() != r2; }
}
class CommonCode;
class RawCodeException : public std::runtime_error {
public:
RawCodeException() : std::runtime_error("invalid raw code") {}
explicit RawCodeException(const std::string &msg) : std::runtime_error(msg) {}
~RawCodeException() noexcept override = default;
};
class RawCode {
uint64_t code_;
RawCode() = default; // unsafe initialize
static inline uint64_t compact(uint64_t raw_code) noexcept; // raw code -> common code
static inline uint64_t extract(uint64_t common_code) noexcept; // common code -> raw code
static inline uint64_t get_vertical_mirror(uint64_t raw_code) noexcept;
static inline uint64_t get_horizontal_mirror(uint64_t raw_code) noexcept;
static inline bool check_vertical_mirror(uint64_t raw_code) noexcept;
static inline bool check_horizontal_mirror(uint64_t raw_code) noexcept;
public:
/// Validity check
bool valid() const noexcept;
static bool check(uint64_t raw_code) noexcept;
/// Operators of RawCode
constexpr explicit operator uint64_t() const noexcept { return code_; }
friend std::ostream& operator<<(std::ostream &out, const RawCode &self);
/// Export functions
CommonCode to_common_code() const noexcept;
constexpr uint64_t unwrap() const noexcept { return code_; }
/// RawCode constructors
explicit RawCode(uint64_t raw_code);
explicit RawCode(CommonCode &&common_code) noexcept;
explicit RawCode(const CommonCode &common_code) noexcept;
/// Static initialization
static RawCode create(uint64_t raw_code);
static RawCode unsafe_create(uint64_t raw_code) noexcept;
static RawCode from_common_code(uint64_t common_code);
static RawCode from_common_code(CommonCode &&common_code) noexcept;
static RawCode from_common_code(std::string &&common_code);
static RawCode from_common_code(const CommonCode &common_code) noexcept;
static RawCode from_common_code(const std::string &common_code);
/// Mirror functions
RawCode to_vertical_mirror() const noexcept;
RawCode to_horizontal_mirror() const noexcept;
bool is_vertical_mirror() const noexcept; // whether vertically symmetrical
bool is_horizontal_mirror() const noexcept; // whether horizontally symmetrical
bool is_vertical_mirror(RawCode &&raw_code) const noexcept; // whether vertically symmetric to another
bool is_vertical_mirror(const RawCode &raw_code) const noexcept;
bool is_horizontal_mirror(RawCode &&raw_code) const noexcept; // whether horizontally symmetric to another
bool is_horizontal_mirror(const RawCode &raw_code) const noexcept;
};
inline bool operator==(uint64_t r1, const RawCode &r2) noexcept { return r1 == r2.unwrap(); }
inline bool operator!=(uint64_t r1, const RawCode &r2) noexcept { return r1 != r2.unwrap(); }
inline bool operator==(const RawCode &r1, uint64_t r2) noexcept { return r1.unwrap() == r2; }
inline bool operator!=(const RawCode &r1, uint64_t r2) noexcept { return r1.unwrap() != r2; }
inline bool operator==(const RawCode &r1, const RawCode &r2) noexcept { return r1.unwrap() == r2.unwrap(); }
inline bool operator!=(const RawCode &r1, const RawCode &r2) noexcept { return r1.unwrap() != r2.unwrap(); }
} // namespace klotski

Loading…
Cancel
Save