diff --git a/klotski/common.cc b/klotski/common.cc index 21a2118..8118f23 100644 --- a/klotski/common.cc +++ b/klotski/common.cc @@ -7,7 +7,7 @@ uint32_t Common::range_reverse(uint32_t bin) { // reverse binary every 2-bits return ((bin << 2) & 0xCCCCCCCC) | ((bin >> 2) & 0x33333333); } -bool Common::check_case(uint32_t head, uint32_t range) { // check whether the case is valid +bool Common::check_case(uint32_t head, uint32_t range) { // whether the head and range is valid uint32_t mask = 0b110011 << head; // fill 2x2 block for (int addr = 0; range; range >>= 2) { // traverse every 2-bits while (mask >> addr & 0b1) { @@ -34,7 +34,39 @@ bool Common::check_case(uint32_t head, uint32_t range) { // check whether the ca mask |= 0b11 << addr; // fill 1x2 block break; } - // TODO: should we ensure that low-bits as 0? } return true; // valid case } + +bool Common::check_case_safe(uint32_t head, uint32_t range) { // whether the case is valid + uint32_t space_num = 0; + uint32_t mask = 0b110011 << head; // fill 2x2 block + for (int addr = 0; range; range >>= 2) { // traverse every 2-bits + while (mask >> addr & 0b1) { + ++addr; // search next not filled block + } + switch (range & 0b11) { + case 0b00: // space block + ++space_num; + case 0b11: // 1x1 block + if (addr > 19) { // invalid address + return false; + } + mask |= 0b1 << addr; // fill 1x1 block + break; + case 0b10: // 2x1 block + if (addr > 15 || mask >> (addr + 4) & 0b1) { // invalid address + return false; + } + mask |= 0b10001 << addr; // fill 2x1 block + break; + case 0b01: // 1x2 block + if (addr > 18 || (addr & 0b11) == 0b11 || mask >> (addr + 1) & 0b1) { // invalid address + return false; + } + mask |= 0b11 << addr; // fill 1x2 block + break; + } + } + return space_num >= 2; // at least 2 space +} diff --git a/klotski/common.h b/klotski/common.h index 8c80a6c..505bef1 100644 --- a/klotski/common.h +++ b/klotski/common.h @@ -6,4 +6,5 @@ class Common { public: static uint32_t range_reverse(uint32_t bin); static bool check_case(uint32_t head, uint32_t range); + static bool check_case_safe(uint32_t head, uint32_t range); }; diff --git a/klotski/common_code.cc b/klotski/common_code.cc index fae0267..e4e403d 100644 --- a/klotski/common_code.cc +++ b/klotski/common_code.cc @@ -7,5 +7,5 @@ bool CommonCode::check(uint64_t common_code) { if (head >= 16 || (head & 0b11) == 0b11) { // check 2x2 block address return false; // invalid common code } - return Common::check_case(head, Common::range_reverse(range)); // check by head and range + return Common::check_case_safe(head, Common::range_reverse(range)); // check by head and range } diff --git a/klotski/main.cc b/klotski/main.cc index 47799b7..4b1f2dd 100644 --- a/klotski/main.cc +++ b/klotski/main.cc @@ -46,22 +46,28 @@ int main() { // } // uint32_t sum = 0; - for (uint32_t head = 0; head < 1; ++head) { - auto prefix = (uint64_t)head << 32; - for (uint64_t range = 0; range < 0x100000000; ++range) { - uint64_t code = prefix | range; - if (CommonCode::check(code)) { - printf("%09lX\n", code); +// for (uint32_t head = 0; head < 1; ++head) { +// auto prefix = (uint64_t)head << 32; +// for (uint64_t range = 0; range < 0x100000000; ++range) { +// uint64_t code = prefix | range; +// if (CommonCode::check(code)) { +// printf("%09lX\n", code); // ++sum; - } - +// } // if (range % 0x1000000 == 0) { // std::cout << range / 0x1000000 << std::endl; // } +// } +// } +// std::cout << "sum: " << sum << std::endl; + + uint64_t error_code = 0x02EFFF7C0; - } + if (CommonCode::check(error_code)) { + std::cout << "true" << std::endl; + } else { + std::cout << "false" << std::endl; } -// std::cout << "sum: " << sum << std::endl; return 0; }