|  |  | @ -2,7 +2,7 @@ | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /// ShortCode is a high-compression encoding scheme based on CommonCode. Since there
 | 
			
		
	
		
			
				
					|  |  |  | /// are a total of 29334498 valid klotski layouts, arrange their CommonCodes from
 | 
			
		
	
		
			
				
					|  |  |  | /// small to large (36-bits positive integers), and use the index as the ShortCode.
 | 
			
		
	
		
			
				
					|  |  |  | /// small to large (36-bit positive integers), and use the index as the ShortCode.
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /// Therefore, the valid value of ShortCode is [0, 29334498), stored in `uint32_t`.
 | 
			
		
	
		
			
				
					|  |  |  | /// The goal of high compression ratio is to facilitate verbal sharing, so it is
 | 
			
		
	
	
		
			
				
					|  |  | @ -11,21 +11,21 @@ | 
			
		
	
		
			
				
					|  |  |  | /// and 26 characters, forming a private base32 scheme.
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /// Coincidentally, log(32, 29334498) is approximately equal to `4.96`, so using
 | 
			
		
	
		
			
				
					|  |  |  | /// 5-bits base32 can make good use of space, so any valid klotski layout can be
 | 
			
		
	
		
			
				
					|  |  |  | /// represented by a 5-bits length code. As in CommonCode, the characters here are
 | 
			
		
	
		
			
				
					|  |  |  | /// 5-bit base32 can make good use of space, so any valid klotski layout can be
 | 
			
		
	
		
			
				
					|  |  |  | /// represented by a 5-bit length code. As in CommonCode, the characters here are
 | 
			
		
	
		
			
				
					|  |  |  | /// case insensitive, but uppercase is still recommended.
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | ///   ShortCode Convert Table
 | 
			
		
	
		
			
				
					|  |  |  | ///                ShortCode Convert Table
 | 
			
		
	
		
			
				
					|  |  |  | ///   -------------------------------------------------
 | 
			
		
	
		
			
				
					|  |  |  | ///   |  00 |  01 |  02 |  03 |  04 |  05 |  06 |  07 |
 | 
			
		
	
		
			
				
					|  |  |  | ///   | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` |
 | 
			
		
	
		
			
				
					|  |  |  | ///   -------------------------------------------------
 | 
			
		
	
		
			
				
					|  |  |  | ///   |-----------------------------------------------|
 | 
			
		
	
		
			
				
					|  |  |  | ///   |  08 |  09 |  10 |  11 |  12 |  13 |  14 |  15 |
 | 
			
		
	
		
			
				
					|  |  |  | ///   | `9` | `A` | `B` | `C` | `D` | `E` | `F` | `G` |
 | 
			
		
	
		
			
				
					|  |  |  | ///   -------------------------------------------------
 | 
			
		
	
		
			
				
					|  |  |  | ///   |-----------------------------------------------|
 | 
			
		
	
		
			
				
					|  |  |  | ///   |  16 |  17 |  18 |  19 |  20 |  21 |  22 |  23 |
 | 
			
		
	
		
			
				
					|  |  |  | ///   | `H` | `J` | `K` | `M` | `N` | `P` | `Q` | `R` |
 | 
			
		
	
		
			
				
					|  |  |  | ///   -------------------------------------------------
 | 
			
		
	
		
			
				
					|  |  |  | ///   |-----------------------------------------------|
 | 
			
		
	
		
			
				
					|  |  |  | ///   |  24 |  25 |  26 |  27 |  28 |  29 |  30 |  31 |
 | 
			
		
	
		
			
				
					|  |  |  | ///   | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` |
 | 
			
		
	
		
			
				
					|  |  |  | ///   -------------------------------------------------
 | 
			
		
	
	
		
			
				
					|  |  | @ -51,85 +51,93 @@ | 
			
		
	
		
			
				
					|  |  |  | #include <string> | 
			
		
	
		
			
				
					|  |  |  | #include <cstdint> | 
			
		
	
		
			
				
					|  |  |  | #include <ostream> | 
			
		
	
		
			
				
					|  |  |  | #include <stdexcept> | 
			
		
	
		
			
				
					|  |  |  | #include <utility> | 
			
		
	
		
			
				
					|  |  |  | #include <stdexcept> | 
			
		
	
		
			
				
					|  |  |  | #include "all_cases.h" | 
			
		
	
		
			
				
					|  |  |  | #include "common_code.h" | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | namespace klotski { | 
			
		
	
		
			
				
					|  |  |  |     class CommonCode; // import for convert interface
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     const uint32_t SHORT_CODE_LIMIT = klotski::ALL_CASES_SIZE_SUM; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     class ShortCodeException : public std::runtime_error { | 
			
		
	
		
			
				
					|  |  |  |     public: | 
			
		
	
		
			
				
					|  |  |  |         ShortCodeException() : std::runtime_error("invalid short code") {} | 
			
		
	
		
			
				
					|  |  |  |         explicit ShortCodeException(const std::string &msg) : std::runtime_error(msg) {} | 
			
		
	
		
			
				
					|  |  |  |         ~ShortCodeException() noexcept override = default; | 
			
		
	
		
			
				
					|  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     class ShortCode { | 
			
		
	
		
			
				
					|  |  |  |     public: | 
			
		
	
		
			
				
					|  |  |  |         enum Mode {NORMAL, FAST}; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     private: | 
			
		
	
		
			
				
					|  |  |  |         uint32_t code; | 
			
		
	
		
			
				
					|  |  |  |         ShortCode() = default; // unsafe initialize
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         static Mode mode(); | 
			
		
	
		
			
				
					|  |  |  |         static bool fast_mode_available; | 
			
		
	
		
			
				
					|  |  |  |         static bool normal_mode_available; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         static inline uint64_t fast_decode(uint32_t short_code) noexcept; // short code -> common code
 | 
			
		
	
		
			
				
					|  |  |  |         static inline uint32_t fast_encode(uint64_t common_code) noexcept; // common code -> short code
 | 
			
		
	
		
			
				
					|  |  |  |         static inline uint64_t tiny_decode(uint32_t short_code) noexcept; // short code -> common code
 | 
			
		
	
		
			
				
					|  |  |  |         static inline uint32_t tiny_encode(uint64_t common_code) noexcept; // common code -> short code
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         static inline std::string string_encode(uint32_t short_code) noexcept; // short code -> string
 | 
			
		
	
		
			
				
					|  |  |  |         static inline uint32_t string_decode(const std::string &short_code); // string -> short code
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     public: | 
			
		
	
		
			
				
					|  |  |  |         /// ShortCode validity check
 | 
			
		
	
		
			
				
					|  |  |  |         bool valid() const noexcept; | 
			
		
	
		
			
				
					|  |  |  |         static bool check(uint32_t short_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         /// ShortCode convert mode
 | 
			
		
	
		
			
				
					|  |  |  |         static void speed_up(Mode mode); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         /// Operators of ShortCode
 | 
			
		
	
		
			
				
					|  |  |  |         bool operator==(const ShortCode &short_code) const noexcept; | 
			
		
	
		
			
				
					|  |  |  |         bool operator!=(const ShortCode &short_code) const noexcept; | 
			
		
	
		
			
				
					|  |  |  |         constexpr explicit operator uint32_t() const noexcept { return code; } | 
			
		
	
		
			
				
					|  |  |  |         friend std::ostream& operator<<(std::ostream &out, const ShortCode &self); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         /// Export functions
 | 
			
		
	
		
			
				
					|  |  |  |         std::string to_string() const noexcept; | 
			
		
	
		
			
				
					|  |  |  |         CommonCode to_common_code() const noexcept; | 
			
		
	
		
			
				
					|  |  |  |         constexpr uint32_t unwrap() const noexcept { return code; } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         /// ShortCode constructors
 | 
			
		
	
		
			
				
					|  |  |  |         explicit ShortCode(uint32_t short_code); | 
			
		
	
		
			
				
					|  |  |  |         explicit ShortCode(std::string &&short_code); | 
			
		
	
		
			
				
					|  |  |  |         explicit ShortCode(CommonCode &&common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  |         explicit ShortCode(const std::string &short_code); | 
			
		
	
		
			
				
					|  |  |  |         explicit ShortCode(const CommonCode &common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         /// Static initialization
 | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode create(uint32_t short_code); | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode unsafe_create(uint32_t short_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_string(std::string &&short_code); | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_string(const std::string &short_code); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_common_code(uint64_t common_code); | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_common_code(CommonCode &&common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_common_code(std::string &&common_code); | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_common_code(const CommonCode &common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  |         static ShortCode from_common_code(const std::string &common_code); | 
			
		
	
		
			
				
					|  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     inline bool operator==(uint32_t s1, const ShortCode &s2) noexcept { return s1 == s2.unwrap(); } | 
			
		
	
		
			
				
					|  |  |  |     inline bool operator!=(uint32_t s1, const ShortCode &s2) noexcept { return s1 != s2.unwrap(); } | 
			
		
	
		
			
				
					|  |  |  |     inline bool operator==(const ShortCode &s1, uint32_t s2) noexcept { return s1.unwrap() == s2; } | 
			
		
	
		
			
				
					|  |  |  |     inline bool operator!=(const ShortCode &s1, uint32_t s2) noexcept { return s1.unwrap() != s2; } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | class CommonCode; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | const uint32_t SHORT_CODE_LIMIT = klotski::ALL_CASES_SIZE_SUM; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | class ShortCodeException : public std::runtime_error { | 
			
		
	
		
			
				
					|  |  |  | public: | 
			
		
	
		
			
				
					|  |  |  |     ShortCodeException() : std::runtime_error("invalid short code") {} | 
			
		
	
		
			
				
					|  |  |  |     explicit ShortCodeException(const std::string &msg) : std::runtime_error(msg) {} | 
			
		
	
		
			
				
					|  |  |  |     ~ShortCodeException() noexcept override = default; | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /// For ShortCode, you must choose at least one mode (NORMAL or FAST) to convert, and
 | 
			
		
	
		
			
				
					|  |  |  | /// they all need a certain amount of time to warm up. `NORMAL` warms up quickly, and
 | 
			
		
	
		
			
				
					|  |  |  | /// `FAST` is slower, but the conversion speed of `FAST` is much faster than `NORMAL`.
 | 
			
		
	
		
			
				
					|  |  |  | /// When only converting a small amount of codes, please choose NORMAL mode. Otherwise
 | 
			
		
	
		
			
				
					|  |  |  | /// FAST mode should be used.
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | class ShortCode { | 
			
		
	
		
			
				
					|  |  |  | public: | 
			
		
	
		
			
				
					|  |  |  |     enum Mode {NORMAL, FAST}; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | private: | 
			
		
	
		
			
				
					|  |  |  |     uint32_t code_; | 
			
		
	
		
			
				
					|  |  |  |     ShortCode() = default; // unsafe initialize
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     static Mode mode(); | 
			
		
	
		
			
				
					|  |  |  |     static bool fast_mode_available_; | 
			
		
	
		
			
				
					|  |  |  |     static bool normal_mode_available_; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     static inline uint64_t fast_decode(uint32_t short_code) noexcept; // short code -> common code
 | 
			
		
	
		
			
				
					|  |  |  |     static inline uint32_t fast_encode(uint64_t common_code) noexcept; // common code -> short code
 | 
			
		
	
		
			
				
					|  |  |  |     static inline uint64_t tiny_decode(uint32_t short_code) noexcept; // short code -> common code
 | 
			
		
	
		
			
				
					|  |  |  |     static inline uint32_t tiny_encode(uint64_t common_code) noexcept; // common code -> short code
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     static inline uint32_t string_decode(const std::string &short_code); | 
			
		
	
		
			
				
					|  |  |  |     static inline std::string string_encode(uint32_t short_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | public: | 
			
		
	
		
			
				
					|  |  |  |     /// Validity check
 | 
			
		
	
		
			
				
					|  |  |  |     bool valid() const noexcept; | 
			
		
	
		
			
				
					|  |  |  |     static bool check(uint32_t short_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     /// ShortCode convert mode
 | 
			
		
	
		
			
				
					|  |  |  |     static void speed_up(Mode mode); // {} -> {NORMAL} -> {FAST}
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     /// Operators of ShortCode
 | 
			
		
	
		
			
				
					|  |  |  |     constexpr explicit operator uint32_t() const noexcept { return code_; } | 
			
		
	
		
			
				
					|  |  |  |     friend std::ostream& operator<<(std::ostream &out, const ShortCode &self); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     /// Export functions
 | 
			
		
	
		
			
				
					|  |  |  |     std::string to_string() const noexcept; | 
			
		
	
		
			
				
					|  |  |  |     CommonCode to_common_code() const noexcept; | 
			
		
	
		
			
				
					|  |  |  |     constexpr uint32_t unwrap() const noexcept { return code_; } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     /// ShortCode constructors
 | 
			
		
	
		
			
				
					|  |  |  |     explicit ShortCode(uint32_t short_code); | 
			
		
	
		
			
				
					|  |  |  |     explicit ShortCode(std::string &&short_code); | 
			
		
	
		
			
				
					|  |  |  |     explicit ShortCode(CommonCode &&common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  |     explicit ShortCode(const std::string &short_code); | 
			
		
	
		
			
				
					|  |  |  |     explicit ShortCode(const CommonCode &common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     /// Static initialization
 | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode create(uint32_t short_code); | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode unsafe_create(uint32_t short_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_string(std::string &&short_code); | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_string(const std::string &short_code); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_common_code(uint64_t common_code); | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_common_code(CommonCode &&common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_common_code(std::string &&common_code); | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_common_code(const CommonCode &common_code) noexcept; | 
			
		
	
		
			
				
					|  |  |  |     static ShortCode from_common_code(const std::string &common_code); | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | inline bool operator==(uint32_t s1, const ShortCode &s2) noexcept { return s1 == s2.unwrap(); } | 
			
		
	
		
			
				
					|  |  |  | inline bool operator!=(uint32_t s1, const ShortCode &s2) noexcept { return s1 != s2.unwrap(); } | 
			
		
	
		
			
				
					|  |  |  | inline bool operator==(const ShortCode &s1, uint32_t s2) noexcept { return s1.unwrap() == s2; } | 
			
		
	
		
			
				
					|  |  |  | inline bool operator!=(const ShortCode &s1, uint32_t s2) noexcept { return s1.unwrap() != s2; } | 
			
		
	
		
			
				
					|  |  |  | inline bool operator==(const ShortCode &s1, const ShortCode &s2) noexcept { return s1.unwrap() == s2.unwrap(); } | 
			
		
	
		
			
				
					|  |  |  | inline bool operator!=(const ShortCode &s1, const ShortCode &s2) noexcept { return s1.unwrap() != s2.unwrap(); } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | } // namespace klotski
 | 
			
		
	
	
		
			
				
					|  |  | 
 |