mirror of https://github.com/dnomd343/klotski.git
Dnomd343
7 months ago
9 changed files with 468 additions and 7 deletions
@ -0,0 +1,66 @@ |
|||||
|
#include <iostream> |
||||
|
|
||||
|
#include <benchmark/benchmark.h> |
||||
|
#include <group/group.h> |
||||
|
|
||||
|
#include "all_cases/all_cases.h" |
||||
|
|
||||
|
using klotski::cases::AllCases; |
||||
|
|
||||
|
/// Build all valid CommonCodes.
|
||||
|
static std::vector<uint64_t> all_common_codes() { |
||||
|
std::vector<uint64_t> codes; |
||||
|
for (uint64_t head = 0; head < 16; ++head) { |
||||
|
for (const auto range : AllCases::instance().fetch()[head]) { |
||||
|
codes.emplace_back(head << 32 | range); |
||||
|
} |
||||
|
} |
||||
|
std::cout << "do cal complete" << std::endl; |
||||
|
return codes; |
||||
|
} |
||||
|
|
||||
|
std::vector<uint64_t> common_code_samples(uint64_t num) { |
||||
|
|
||||
|
static auto codes = all_common_codes(); |
||||
|
|
||||
|
uint64_t part_size = codes.size() / num; |
||||
|
|
||||
|
// uint64_t offset = 0;
|
||||
|
uint64_t offset = part_size / 2; |
||||
|
|
||||
|
std::vector<uint64_t> result; |
||||
|
|
||||
|
for (uint64_t i = 0; i < num; ++i) { |
||||
|
uint64_t index = i * part_size + offset; |
||||
|
// // std::cout << "index = " << index << std::endl;
|
||||
|
|
||||
|
// uint64_t kk[] {343, 666, 114514, 35324, 123454, 76453, 93411};
|
||||
|
// uint64_t index = kk[i % 7];
|
||||
|
|
||||
|
result.emplace_back(codes[index]); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
static void CommonCodeToTypeId(benchmark::State &state) { |
||||
|
|
||||
|
auto samples = common_code_samples(state.range(0)); |
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
|
||||
|
for (auto code : samples) { |
||||
|
|
||||
|
volatile auto ret = klotski::cases::common_code_to_type_id(code); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
state.SetItemsProcessed(state.iterations() * state.range(0)); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
BENCHMARK(CommonCodeToTypeId)->Arg(8)->Arg(64)->Arg(256); |
||||
|
|
||||
|
BENCHMARK_MAIN(); |
@ -0,0 +1,51 @@ |
|||||
|
#include <gtest/gtest.h> |
||||
|
|
||||
|
#include "core/core.h" |
||||
|
|
||||
|
#include <unordered_set> |
||||
|
|
||||
|
#include "all_cases/all_cases.h" |
||||
|
#include "common_code/common_code.h" |
||||
|
|
||||
|
using klotski::core::Core; |
||||
|
using klotski::cases::AllCases; |
||||
|
using klotski::codec::CommonCode; |
||||
|
|
||||
|
// mask test
|
||||
|
|
||||
|
TEST(core, core) { |
||||
|
|
||||
|
std::vector<uint64_t> raw_codes; |
||||
|
raw_codes.reserve(klotski::cases::ALL_CASES_NUM_); |
||||
|
|
||||
|
// std::unordered_set<uint64_t> codes;
|
||||
|
// codes.reserve(klotski::cases::ALL_CASES_NUM_);
|
||||
|
|
||||
|
for (uint64_t head = 0; head < 16; ++head) { |
||||
|
for (const auto range : AllCases::instance().fetch()[head]) { |
||||
|
auto common_code = CommonCode::unsafe_create(head << 32 | range); |
||||
|
auto raw_code = common_code.to_raw_code().unwrap(); |
||||
|
|
||||
|
raw_codes.emplace_back(raw_code); |
||||
|
// codes.emplace(raw_code);
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// auto core = Core([&codes](uint64_t ret, uint64_t) {
|
||||
|
// EXPECT_EQ(codes.count(ret), 1);
|
||||
|
// });
|
||||
|
|
||||
|
std::vector<uint64_t> codes; |
||||
|
codes.reserve(402258220); |
||||
|
|
||||
|
auto core = Core([&codes](uint64_t ret, uint64_t) { |
||||
|
codes.emplace_back(klotski::codec::RawCode::unsafe_create(ret).to_common_code().unwrap()); |
||||
|
}); |
||||
|
|
||||
|
for (auto raw_code : raw_codes) { |
||||
|
core.next_cases(raw_code, 0); |
||||
|
} |
||||
|
|
||||
|
// std::cout << codes.size() << std::endl;
|
||||
|
|
||||
|
} |
@ -0,0 +1,149 @@ |
|||||
|
#include <common.h> |
||||
|
#include <gtest/gtest.h> |
||||
|
|
||||
|
#include <thread> |
||||
|
|
||||
|
#include <md5.h> |
||||
|
|
||||
|
#include "group/group.h" |
||||
|
#include "all_cases/all_cases.h" |
||||
|
|
||||
|
using klotski::range_reverse; |
||||
|
|
||||
|
using klotski::cases::AllCases; |
||||
|
using klotski::codec::CommonCode; |
||||
|
|
||||
|
using klotski::cases::ALL_CASES_NUM; |
||||
|
|
||||
|
struct block_num_t { |
||||
|
uint8_t n_1x1 = 0; /// [0, 14]
|
||||
|
uint8_t n_1x2 = 0; /// [0, 7]
|
||||
|
uint8_t n_2x1 = 0; /// [0, 7]
|
||||
|
}; |
||||
|
|
||||
|
bool operator==(block_num_t b1, block_num_t b2) { |
||||
|
return (b1.n_1x1 == b2.n_1x1) && (b1.n_1x2 == b2.n_1x2) && (b1.n_2x1 == b2.n_2x1); |
||||
|
} |
||||
|
|
||||
|
const char BLOCK_NUM_MD5[] = "46a7b3af6d039cbe2f7eaebdd196c6a2"; |
||||
|
|
||||
|
block_num_t common_block_num(const uint64_t common_code) noexcept { |
||||
|
block_num_t result; |
||||
|
auto range = range_reverse(static_cast<uint32_t>(common_code)); |
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
block_num_t raw_block_num(const uint64_t raw_code) noexcept { |
||||
|
block_num_t result; |
||||
|
auto tmp = raw_code; |
||||
|
for (int addr = 0; addr < 20; ++addr, tmp >>= 3) { |
||||
|
switch (tmp & 0b111) { |
||||
|
case BLOCK_1x1: |
||||
|
++result.n_1x1; |
||||
|
continue; |
||||
|
case BLOCK_1x2: |
||||
|
++result.n_1x2; |
||||
|
continue; |
||||
|
case BLOCK_2x1: |
||||
|
++result.n_2x1; |
||||
|
continue; |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
const uint16_t TYPE_ID_INDEX[203] = { |
||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 256, |
||||
|
257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 272, 273, 274, 275, |
||||
|
276, 277, 278, 279, 280, 281, 282, 283, 284, 512, 513, 514, 515, 516, 517, 518, |
||||
|
519, 520, 521, 522, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 544, |
||||
|
545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 768, 769, 770, 771, 772, 773, |
||||
|
774, 775, 776, 784, 785, 786, 787, 788, 789, 790, 791, 792, 800, 801, 802, 803, |
||||
|
804, 805, 806, 807, 808, 816, 817, 818, 819, 820, 821, 822, 823, 824, 1024, 1025, |
||||
|
1026, 1027, 1028, 1029, 1030, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1056, 1057, 1058, 1059, |
||||
|
1060, 1061, 1062, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1088, 1089, 1090, 1091, 1092, 1093, |
||||
|
1094, 1280, 1281, 1282, 1283, 1284, 1296, 1297, 1298, 1299, 1300, 1312, 1313, 1314, 1315, 1316, |
||||
|
1328, 1329, 1330, 1331, 1332, 1344, 1345, 1346, 1347, 1348, 1360, 1361, 1362, 1363, 1364, 1536, |
||||
|
1537, 1538, 1552, 1553, 1554, 1568, 1569, 1570, 1584, 1585, 1586, 1600, 1601, 1602, 1616, 1617, |
||||
|
1618, 1632, 1633, 1634, 1792, 1808, 1824, 1840, 1856, 1872, 1888, |
||||
|
}; |
||||
|
|
||||
|
uint32_t get_type_id(block_num_t block_num) noexcept { // block_num_t -> type_id
|
||||
|
/// flag -> ... 0000 0xxx 0xxx xxxx
|
||||
|
/// n_x2x n_2x1 n_1x1
|
||||
|
auto n_x2x = block_num.n_1x2 + block_num.n_2x1; |
||||
|
auto flag = (n_x2x << 8) | (block_num.n_2x1 << 4) | block_num.n_1x1; |
||||
|
return std::lower_bound(TYPE_ID_INDEX, TYPE_ID_INDEX + klotski::cases::TYPE_ID_LIMIT, flag) - TYPE_ID_INDEX; |
||||
|
} |
||||
|
|
||||
|
TEST(Group, block_num) { |
||||
|
std::string result[16]; |
||||
|
auto test = [&result](uint64_t head) { |
||||
|
char buffer[13]; |
||||
|
result[head].reserve(ALL_CASES_NUM[head]); // vector pre-allocated
|
||||
|
|
||||
|
for (const auto range: AllCases::instance().fetch()[head]) { |
||||
|
auto common_code = CommonCode::unsafe_create(head << 32 | range); |
||||
|
|
||||
|
auto tmp = common_block_num(common_code.unwrap()); |
||||
|
EXPECT_EQ(tmp, raw_block_num(common_code.to_raw_code().unwrap())); |
||||
|
|
||||
|
EXPECT_LE(tmp.n_1x2 * 2 + tmp.n_2x1 * 2 + tmp.n_1x1, 14); |
||||
|
sprintf(buffer, "%d,%d,%d\n", tmp.n_1x2 + tmp.n_2x1, tmp.n_1x1, tmp.n_2x1); |
||||
|
result[head] += buffer; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
std::thread threads[16]; |
||||
|
for (uint64_t head = 0; head < 16; ++head) { |
||||
|
threads[head] = std::thread(test, head); // multi-threads verify
|
||||
|
} |
||||
|
for (auto &t : threads) { t.join(); } // build string data
|
||||
|
|
||||
|
std::string block_num_str; |
||||
|
for (auto &&tmp : result) { |
||||
|
block_num_str += tmp; // combine result
|
||||
|
} |
||||
|
auto block_num_md5 = md5::MD5::Hash(block_num_str.c_str(), block_num_str.size()); |
||||
|
EXPECT_STREQ(block_num_md5.c_str(), BLOCK_NUM_MD5); // verify md5
|
||||
|
} |
||||
|
|
||||
|
TEST(Group, common_code) { |
||||
|
|
||||
|
for (uint64_t head = 0; head < 16; ++head) { |
||||
|
for (const auto range : AllCases::instance().fetch()[head]) { |
||||
|
|
||||
|
auto common_code = (head << 32 | range); |
||||
|
|
||||
|
EXPECT_EQ(klotski::cases::common_code_to_type_id(common_code), get_type_id(common_block_num(common_code))); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
TEST(Group, raw_code) { |
||||
|
for (uint64_t head = 0; head < 16; ++head) { |
||||
|
for (const auto range : AllCases::instance().fetch()[head]) { |
||||
|
|
||||
|
auto raw_code = CommonCode::unsafe_create(head << 32 | range).to_raw_code().unwrap(); |
||||
|
|
||||
|
EXPECT_EQ(klotski::cases::raw_code_to_type_id(raw_code), get_type_id(raw_block_num(raw_code))); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
Loading…
Reference in new issue