mirror of https://github.com/dnomd343/klotski.git
Dnomd343
2 years ago
5 changed files with 154 additions and 100 deletions
@ -1,3 +1,3 @@ |
|||||
cmake_minimum_required(VERSION 3.0) |
cmake_minimum_required(VERSION 3.0) |
||||
|
|
||||
add_library(group OBJECT seeds.cc basic_id.cc build_cases.cc group_info.cc) |
add_library(group OBJECT basic.cc seeds.cc build_cases.cc group_info.cc) |
||||
|
@ -0,0 +1,151 @@ |
|||||
|
#include <thread> |
||||
|
#include <algorithm> |
||||
|
#include "md5.h" |
||||
|
#include "group.h" |
||||
|
#include "type_id.h" |
||||
|
#include "all_cases.h" |
||||
|
#include "tiny_pool.h" |
||||
|
#include "group_seeds.h" |
||||
|
#include "gtest/gtest.h" |
||||
|
|
||||
|
#define SHOULD_PANIC(FUNC) \ |
||||
|
try { \ |
||||
|
FUNC; EXPECT_STREQ("should panic", "but no panic"); \ |
||||
|
} catch (...) {} |
||||
|
|
||||
|
using klotski::Group; |
||||
|
using klotski::GroupCase; |
||||
|
using klotski::GroupType; |
||||
|
|
||||
|
using klotski::RawCode; |
||||
|
using klotski::AllCases; |
||||
|
using klotski::CommonCode; |
||||
|
|
||||
|
using klotski::GROUP_SEEDS; |
||||
|
using klotski::TYPE_ID_LIMIT; |
||||
|
using klotski::ALL_CASES_SIZE; |
||||
|
using klotski::TYPE_ID_GROUP_NUM; |
||||
|
|
||||
|
const char BLOCK_NUM_MD5[] = "46a7b3af6d039cbe2f7eaebdd196c6a2"; |
||||
|
|
||||
|
TEST(Group, type_id) { |
||||
|
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { |
||||
|
EXPECT_EQ(GroupType(type_id).unwrap(), type_id); |
||||
|
} |
||||
|
SHOULD_PANIC(GroupType{TYPE_ID_LIMIT}) // type id overflow
|
||||
|
|
||||
|
auto test = [](uint64_t head) { |
||||
|
for (auto &&range: AllCases::fetch()[head]) { |
||||
|
auto common_code = CommonCode::unsafe_create(head << 32 | range); |
||||
|
auto raw_code = RawCode::from_common_code(common_code); |
||||
|
|
||||
|
auto type_id = GroupType(common_code); |
||||
|
EXPECT_EQ(type_id, GroupType(raw_code)); |
||||
|
EXPECT_LT(type_id.unwrap(), TYPE_ID_LIMIT); // type_id <= TYPE_ID_LIMIT
|
||||
|
EXPECT_EQ(type_id.block_num(), GroupType::block_num(raw_code)); |
||||
|
EXPECT_EQ(type_id.block_num(), GroupType::block_num(common_code)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
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(); } |
||||
|
} |
||||
|
|
||||
|
TEST(Group, block_num) { |
||||
|
std::string result[16]; |
||||
|
auto test = [&result](uint64_t head) { |
||||
|
char buffer[13]; |
||||
|
result[head].reserve(ALL_CASES_SIZE[head]); // vector pre-allocated
|
||||
|
|
||||
|
for (auto &&range: AllCases::fetch()[head]) { |
||||
|
auto common_code = CommonCode::unsafe_create(head << 32 | range); |
||||
|
auto tmp = GroupType(common_code).block_num(); |
||||
|
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(block_num_str.c_str(), block_num_str.size()); |
||||
|
EXPECT_STREQ(block_num_md5.c_str(), BLOCK_NUM_MD5); // verify md5
|
||||
|
} |
||||
|
|
||||
|
TEST(Group, group_id) { |
||||
|
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { |
||||
|
for (uint32_t group_id = 0; group_id < TYPE_ID_GROUP_NUM[type_id]; ++group_id) { |
||||
|
auto tmp = Group(type_id, group_id); |
||||
|
EXPECT_EQ(tmp, Group(GroupType(type_id), group_id)); |
||||
|
EXPECT_EQ(tmp.type_id(), type_id); |
||||
|
EXPECT_EQ(tmp.unwrap(), group_id); |
||||
|
} |
||||
|
SHOULD_PANIC(Group(type_id, TYPE_ID_GROUP_NUM[type_id])) // group_id overflow
|
||||
|
} |
||||
|
SHOULD_PANIC(Group(TYPE_ID_LIMIT, 0)) // type_id overflow
|
||||
|
|
||||
|
auto test = [](CommonCode seed) { |
||||
|
auto tmp = Group(seed); |
||||
|
EXPECT_EQ(tmp, Group(seed.to_raw_code())); |
||||
|
EXPECT_EQ(tmp.type_id(), GroupType(seed).unwrap()); |
||||
|
|
||||
|
auto size = tmp.size(); |
||||
|
EXPECT_EQ(size, Group::size(seed)); |
||||
|
EXPECT_EQ(size, Group::size(seed.to_raw_code())); |
||||
|
|
||||
|
EXPECT_EQ(seed, tmp.seed()); |
||||
|
EXPECT_EQ(seed, Group::seed(seed)); |
||||
|
EXPECT_EQ(seed, Group::seed(seed.to_raw_code())); |
||||
|
|
||||
|
auto sort = [](std::vector<RawCode> &&cases) -> std::vector<CommonCode> { |
||||
|
std::vector<CommonCode> group{cases.begin(), cases.end()}; |
||||
|
std::sort(group.begin(), group.end()); |
||||
|
return group; |
||||
|
}; |
||||
|
auto cases = sort(tmp.cases()); |
||||
|
EXPECT_EQ(cases, sort(Group::cases(seed))); |
||||
|
EXPECT_EQ(cases, sort(Group::cases(seed.to_raw_code()))); |
||||
|
}; |
||||
|
|
||||
|
TinyPool pool; |
||||
|
for (auto &&seed : GROUP_SEEDS) { |
||||
|
pool.submit(test, CommonCode(seed)); |
||||
|
} |
||||
|
pool.boot(); |
||||
|
pool.join(); |
||||
|
} |
||||
|
|
||||
|
// TODO: test Group(...).unwrap() == group_id
|
||||
|
// TODO: test Group::size() / Group::seed() / Group::cases()
|
||||
|
|
||||
|
TEST(Group, operators) { |
||||
|
EXPECT_EQ(GroupType(0), GroupType(0)); |
||||
|
EXPECT_NE(GroupType(0), GroupType(1)); |
||||
|
|
||||
|
EXPECT_EQ(Group(123, 0), Group(123, 0)); |
||||
|
EXPECT_NE(Group(123, 0), Group(123, 1)); |
||||
|
EXPECT_NE(Group(123, 0), Group(124, 0)); |
||||
|
|
||||
|
auto block_num = GroupType::block_num_t{0, 0, 0}; |
||||
|
EXPECT_EQ(block_num, (GroupType::block_num_t{0, 0, 0})); |
||||
|
EXPECT_NE(block_num, (GroupType::block_num_t{1, 0, 0})); |
||||
|
EXPECT_NE(block_num, (GroupType::block_num_t{0, 1, 0})); |
||||
|
EXPECT_NE(block_num, (GroupType::block_num_t{0, 0, 1})); |
||||
|
|
||||
|
auto info = GroupCase::info_t{0, 0, 0}; |
||||
|
EXPECT_EQ(info, (GroupCase::info_t{0, 0, 0})); |
||||
|
EXPECT_NE(info, (GroupCase::info_t{1, 0, 0})); |
||||
|
EXPECT_NE(info, (GroupCase::info_t{0, 1, 0})); |
||||
|
EXPECT_NE(info, (GroupCase::info_t{0, 0, 1})); |
||||
|
} |
@ -1,97 +0,0 @@ |
|||||
#include <thread> |
|
||||
#include "md5.h" |
|
||||
#include "group.h" |
|
||||
#include "type_id.h" |
|
||||
#include "all_cases.h" |
|
||||
#include "gtest/gtest.h" |
|
||||
|
|
||||
using klotski::TypeId; |
|
||||
using klotski::GroupId; |
|
||||
using klotski::RawCode; |
|
||||
using klotski::AllCases; |
|
||||
using klotski::CommonCode; |
|
||||
|
|
||||
using klotski::TYPE_ID_LIMIT; |
|
||||
using klotski::ALL_CASES_SIZE; |
|
||||
using klotski::TYPE_ID_GROUP_NUM; |
|
||||
|
|
||||
const char BLOCK_NUM_MD5[] = "46a7b3af6d039cbe2f7eaebdd196c6a2"; |
|
||||
|
|
||||
TEST(Group, type_id) { |
|
||||
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { |
|
||||
EXPECT_EQ(TypeId(type_id).unwrap(), type_id); |
|
||||
} |
|
||||
try { |
|
||||
EXPECT_EQ(TypeId(TYPE_ID_LIMIT).unwrap(), -1); |
|
||||
} catch (...) {} // should panic
|
|
||||
|
|
||||
auto test = [](uint64_t head) { |
|
||||
for (auto &&range: AllCases::fetch()[head]) { |
|
||||
auto common_code = CommonCode::unsafe_create(head << 32 | range); |
|
||||
auto raw_code = RawCode::from_common_code(common_code); |
|
||||
|
|
||||
auto type_id = TypeId(common_code); |
|
||||
EXPECT_EQ(type_id, TypeId(raw_code)); |
|
||||
EXPECT_LT(type_id.unwrap(), TYPE_ID_LIMIT); |
|
||||
EXPECT_EQ(type_id.block_num(), TypeId::block_num(raw_code)); |
|
||||
EXPECT_EQ(type_id.block_num(), TypeId::block_num(common_code)); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
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(); } |
|
||||
} |
|
||||
|
|
||||
TEST(Group, block_num) { |
|
||||
std::string result[16]; |
|
||||
auto test = [&result](uint64_t head) { |
|
||||
char buffer[13]; |
|
||||
result[head].reserve(ALL_CASES_SIZE[head]); // vector pre-allocated
|
|
||||
for (auto &&range: AllCases::fetch()[head]) { |
|
||||
auto common_code = CommonCode::unsafe_create(head << 32 | range); |
|
||||
auto tmp = TypeId(common_code).block_num(); |
|
||||
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(); } |
|
||||
|
|
||||
std::string block_num_str; |
|
||||
for (auto &&tmp : result) { |
|
||||
block_num_str += tmp; // combine result
|
|
||||
} |
|
||||
auto block_num_md5 = md5(block_num_str.c_str(), block_num_str.size()); |
|
||||
EXPECT_STREQ(block_num_md5.c_str(), BLOCK_NUM_MD5); // verify md5
|
|
||||
} |
|
||||
|
|
||||
TEST(Group, group_id) { |
|
||||
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { |
|
||||
for (uint32_t group_id = 0; group_id < TYPE_ID_GROUP_NUM[type_id]; ++group_id) { |
|
||||
auto gid = GroupId(type_id, group_id); |
|
||||
EXPECT_EQ(gid, GroupId(TypeId(type_id), group_id)); |
|
||||
EXPECT_EQ(gid.type_id(), type_id); |
|
||||
EXPECT_EQ(gid.unwrap(), group_id); |
|
||||
} |
|
||||
try { |
|
||||
EXPECT_EQ(GroupId(type_id, TYPE_ID_GROUP_NUM[type_id]).unwrap(), -1); |
|
||||
} catch (...) {} // should panic
|
|
||||
} |
|
||||
|
|
||||
// TODO: test GroupId(...)
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
TEST(Group, operators) { |
|
||||
// TODO: TypeId
|
|
||||
// TODO: block_num_t
|
|
||||
// TODO: GroupId
|
|
||||
} |
|
Loading…
Reference in new issue