#include #include #include "core.h" #include "group.h" #include "common.h" #include "absl/container/flat_hash_map.h" #include "type_id.h" namespace klotski { using Common::range_reverse; Group::block_num_t Group::block_num(uint32_t type_id) { // jiang_num (n_x2x) // bing_num (n_1x1) // style_num (n_2x1) auto tids = std::vector(); uint32_t count = 0; for (int n_x2x = 0; n_x2x <= 7; ++n_x2x) for (int n_2x1 = 0; n_2x1 <= n_x2x; ++n_2x1) for (int n_1x1 = 0; n_1x1 <= (14 - n_x2x * 2); ++n_1x1) { ++count; uint32_t tid = (n_x2x << 8) | (n_2x1 << 4) | n_1x1; tids.emplace_back(tid); std::cout << n_x2x << " " << n_1x1 << " " << n_2x1 << "(" << tid << ")" << std::endl; } // std::cout << count << std::endl; // for (int i = 0; i < tids.size(); ++i) { // // printf("% 5d,", tids[i]); // // if ((i & 0b111) == 0b111) { // printf("\n"); // } // std::cout << tid << std::endl; // } // generate(generate_t { // generate target ranges // .n1 = 16 - n * 2 - n_1x1, /// space -> 00 // .n2 = n - n_2x1, /// 1x2 -> 01 // .n3 = n_2x1, /// 2x1 -> 10 // .n4 = n_1x1, /// 1x1 -> 11 // }); return Group::block_num_t(); } Group::block_num_t Group::block_num(const RawCode &raw_code) { block_num_t result; auto tmp = raw_code.unwrap(); for (int addr = 0; addr < 20; ++addr, tmp >>= 3) { switch (tmp & 0b111) { case B_1x1: ++result.n_1x1; continue; case B_1x2: ++result.n_1x2; continue; case B_2x1: ++result.n_2x1; continue; } } return result; } Group::block_num_t Group::block_num(const CommonCode &common_code) { block_num_t result; auto range = range_reverse((uint32_t)common_code.unwrap()); for (; range; range >>= 2) { switch (range & 0b11) { case 0b01: /// 1x2 block ++result.n_1x2; continue; case 0b10: /// 2x1 block ++result.n_2x1; continue; case 0b11: /// 1x1 block ++result.n_1x1; continue; } } return result; } std::vector Group::group_cases(const RawCode &seed) { std::queue cache; absl::flat_hash_map cases; // cases.reserve(max_group_size(seed)); cases.emplace(seed.unwrap(), 0); // without mask cache.emplace(seed.unwrap()); auto core = Core( [&cache, &cases](auto &&code, auto &&mask) { // callback function auto current = cases.find(code); if (current != cases.end()) { current->second |= mask; // update mask return; } cases.emplace(code, mask); cache.emplace(code); } ); while (!cache.empty()) { // until BFS without elements core.next_cases(cache.front(), cases.find(cache.front())->second); cache.pop(); // case dequeue } auto result = std::vector(); result.reserve(cases.size()); for (auto &&raw_code : cases) { // export group cases result.emplace_back(RawCode::unsafe_create(raw_code.first)); } return result; } } // namespace klotski