diff --git a/klotski/short_code.h b/klotski/short_code.h index 0c0da18..7487f21 100644 --- a/klotski/short_code.h +++ b/klotski/short_code.h @@ -5,6 +5,7 @@ #include #include +/// ok const char SHORT_CODE_TABLE[32] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', // skip `0` 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // skip `I` @@ -13,6 +14,7 @@ const char SHORT_CODE_TABLE[32] = { 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', }; +/// ok const char SHORT_CODE_TABLE_REV[42] = { // 00 01 02 03 04 05 06 07 08 0, 1, 2, 3, 4, 5, 6, 7, 8, @@ -28,9 +30,10 @@ const char SHORT_CODE_TABLE_REV[42] = { class ShortCode { public: - // ok + /// ok enum Mode {NORMAL, FAST}; + /// ok ShortCode() = default; void speed_up(enum Mode mode); explicit ShortCode(enum Mode mode); @@ -39,19 +42,20 @@ public: uint32_t zip_short_code(uint64_t common_code); uint64_t unzip_short_code(uint32_t short_code); + /// ok static std::string code_to_string(uint32_t short_code); static uint32_t code_from_string(const std::string &short_code); private: - // ok + /// ok static const uint32_t SHORT_CODE_LIMIT = 29334498; - // ok + /// ok std::vector basic_ranges; std::vector all_cases_list; // short_code -> common_code std::unordered_map all_cases_dict; // common_code -> short_code - // ok + /// ok void build_mappings(); enum Mode check_mode(); void build_base_ranges(); diff --git a/src/main.cc b/src/main.cc index 14dadc2..ca0b360 100644 --- a/src/main.cc +++ b/src/main.cc @@ -100,6 +100,8 @@ int main() { auto s = ShortCode(14323231); std::cout << s.unwrap() << std::endl; std::cout << s.to_string() << std::endl; + std::cout << ShortCode("EP4HZ").unwrap() << std::endl; + std::cout << ShortCode("eP4hZ").to_string() << std::endl; return 0; } diff --git a/src/short_code/short_code.cc b/src/short_code/short_code.cc index 24c2f13..65422b8 100644 --- a/src/short_code/short_code.cc +++ b/src/short_code/short_code.cc @@ -1,4 +1,5 @@ #include "short_code.h" +#include "short_code_chars.h" uint32_t ShortCode::unwrap() const { return code; // get raw uint32_t code @@ -15,13 +16,39 @@ ShortCode::ShortCode(uint32_t short_code) { code = short_code; } -#include - -std::string ShortCode::to_string() const { +ShortCode::ShortCode(const std::string &short_code_str) { // 5-bits string decode + if (short_code_str.length() != 5) { // check string length + throw std::invalid_argument("short code format error"); + } - // this->code ==> std::string + uint64_t short_code = 0; + for (auto bit : short_code_str) { + short_code *= 32; + if (bit >= 'a' && bit <= 'z') { + bit -= 32; // convert to uppercase + } + if (bit >= '1' && bit <= 'Z') { + short_code += (bit = SHORT_CODE_TABLE_REV[bit - 49]); // table convert + if (bit != -1) { + continue; // pass check + } + } + throw std::invalid_argument("short code format error"); // unknown characters + } - std::cout << "short code: " << code << std::endl; + if (!ShortCode::check(short_code)) { // check converted short code + throw std::invalid_argument("invalid short code"); + } + code = short_code; +} - return ""; +std::string ShortCode::to_string() const { // encode as 5-bits string + uint32_t short_code = code; + std::string result(5, '\0'); // short code length 5 + for (int n = 0; n < 5; ++n) { + uint8_t bit = short_code % 32; + short_code = (short_code - bit) / 32; + result[4 - n] = SHORT_CODE_TABLE[bit]; + } + return result; } diff --git a/src/short_code/short_code.h b/src/short_code/short_code.h index 583eb0c..9c70989 100644 --- a/src/short_code/short_code.h +++ b/src/short_code/short_code.h @@ -20,7 +20,7 @@ public: std::string to_string() const; explicit ShortCode(uint32_t short_code); -// explicit CommonCode(const std::string &common_code_str); + explicit ShortCode(const std::string &short_code_str); diff --git a/src/short_code/short_code_chars.h b/src/short_code/short_code_chars.h new file mode 100644 index 0000000..cb4b748 --- /dev/null +++ b/src/short_code/short_code_chars.h @@ -0,0 +1,22 @@ +#pragma once + +const char SHORT_CODE_TABLE[32] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', // skip `0` + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // skip `I` + 'J', 'K', // skip `L` + 'M', 'N', // skip `O` + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', +}; + +const char SHORT_CODE_TABLE_REV[42] = { +// 00 01 02 03 04 05 06 07 08 + 0, 1, 2, 3, 4, 5, 6, 7, 8, +// 09 10 11 12 13 14 15 + -1, -1, -1, -1, -1, -1, -1, +// 16 17 18 19 20 21 22 23 24 25 + 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, +// 26 27 28 29 30 31 32 33 34 35 + 18, -1, 19, 20, -1, 21, 22, 23, 24, 25, +// 36 37 38 39 40 41 + 26, 27, 28, 29, 30, 31, +};