mirror of https://github.com/dnomd343/klotski.git
Dnomd343
1 year ago
8 changed files with 269 additions and 29 deletions
@ -0,0 +1,99 @@ |
|||
#include "raw_code.h" |
|||
#include "all_cases.h" |
|||
#include "common_code.h" |
|||
#include "gtest/gtest.h" |
|||
#include "BS_thread_pool.hpp" |
|||
|
|||
using klotski::codec::RawCode; |
|||
using klotski::cases::AllCases; |
|||
|
|||
TEST(RawCode, vertical_mirror) { |
|||
auto raw_code_a = RawCode::unsafe_create(0x0'FC0'480'6DB'FC0'480); // invalid case for test
|
|||
auto raw_code_b1 = RawCode::from_common_code(0x4FEA13400).value(); |
|||
auto raw_code_b2 = RawCode::from_common_code(0x8346AFC00).value(); |
|||
|
|||
EXPECT_TRUE(raw_code_a.is_vertical_mirror()); |
|||
EXPECT_TRUE(raw_code_a.is_vertical_mirror(raw_code_a)); |
|||
EXPECT_EQ(raw_code_a.to_vertical_mirror(), raw_code_a); |
|||
|
|||
EXPECT_FALSE(raw_code_b1.is_vertical_mirror()); |
|||
EXPECT_FALSE(raw_code_b2.is_vertical_mirror()); |
|||
EXPECT_TRUE(raw_code_b1.is_vertical_mirror(raw_code_b2)); |
|||
EXPECT_TRUE(raw_code_b2.is_vertical_mirror(raw_code_b1)); |
|||
EXPECT_EQ(raw_code_b1.to_vertical_mirror(), raw_code_b2); |
|||
EXPECT_EQ(raw_code_b2.to_vertical_mirror(), raw_code_b1); |
|||
|
|||
EXPECT_FALSE(raw_code_a.is_vertical_mirror(raw_code_b1)); |
|||
EXPECT_FALSE(raw_code_a.is_vertical_mirror(raw_code_b2)); |
|||
EXPECT_FALSE(raw_code_b1.is_vertical_mirror(raw_code_a)); |
|||
EXPECT_FALSE(raw_code_b2.is_vertical_mirror(raw_code_a)); |
|||
} |
|||
|
|||
TEST(RawCode, horizontal_mirror) { |
|||
auto raw_code_a = RawCode::from_common_code(0x1A9BF0C00).value(); |
|||
auto raw_code_b1 = RawCode::from_common_code(0x4FEA13400).value(); |
|||
auto raw_code_b2 = RawCode::from_common_code(0x6BFA47000).value(); |
|||
|
|||
EXPECT_TRUE(raw_code_a.is_horizontal_mirror()); |
|||
EXPECT_TRUE(raw_code_a.is_horizontal_mirror(raw_code_a)); |
|||
EXPECT_EQ(raw_code_a.to_horizontal_mirror(), raw_code_a); |
|||
|
|||
EXPECT_FALSE(raw_code_b1.is_horizontal_mirror()); |
|||
EXPECT_FALSE(raw_code_b2.is_horizontal_mirror()); |
|||
EXPECT_TRUE(raw_code_b1.is_horizontal_mirror(raw_code_b2)); |
|||
EXPECT_TRUE(raw_code_b2.is_horizontal_mirror(raw_code_b1)); |
|||
EXPECT_EQ(raw_code_b1.to_horizontal_mirror(), raw_code_b2); |
|||
EXPECT_EQ(raw_code_b2.to_horizontal_mirror(), raw_code_b1); |
|||
|
|||
EXPECT_FALSE(raw_code_a.is_horizontal_mirror(raw_code_b1)); |
|||
EXPECT_FALSE(raw_code_a.is_horizontal_mirror(raw_code_b2)); |
|||
EXPECT_FALSE(raw_code_b1.is_horizontal_mirror(raw_code_a)); |
|||
EXPECT_FALSE(raw_code_b2.is_horizontal_mirror(raw_code_a)); |
|||
} |
|||
|
|||
TEST(RawCode, code_vertical_mirror) { |
|||
auto test_func = [](RawCode code) { |
|||
auto mirror = code.to_vertical_mirror(); |
|||
EXPECT_TRUE(RawCode::check(mirror.unwrap())); |
|||
EXPECT_EQ(mirror.to_common_code().to_raw_code(), mirror); |
|||
EXPECT_EQ(mirror.to_vertical_mirror(), code); |
|||
EXPECT_FALSE(mirror.is_vertical_mirror()); |
|||
EXPECT_NE(code, mirror); |
|||
}; |
|||
|
|||
BS::thread_pool pool; |
|||
for (int head = 0; head < 16; ++head) { |
|||
pool.push_task([&test_func](uint64_t head) { |
|||
for (auto range : AllCases::instance().fetch()[head]) { |
|||
test_func(RawCode::from_common_code(head << 32 | range).value()); |
|||
} |
|||
}, head); |
|||
} |
|||
pool.wait_for_tasks(); |
|||
} |
|||
|
|||
TEST(RawCode, code_horizontal_mirror) { |
|||
auto test_func = [](RawCode code) { |
|||
auto mirror = code.to_horizontal_mirror(); |
|||
EXPECT_TRUE(RawCode::check(mirror.unwrap())); |
|||
EXPECT_EQ(mirror.to_common_code().to_raw_code(), mirror); |
|||
EXPECT_EQ(mirror.to_horizontal_mirror(), code); |
|||
if (mirror.is_horizontal_mirror()) { |
|||
EXPECT_EQ(code, mirror); |
|||
} else { |
|||
EXPECT_NE(code, mirror); |
|||
} |
|||
}; |
|||
|
|||
BS::thread_pool pool; |
|||
for (int head = 0; head < 16; ++head) { |
|||
pool.push_task([&test_func](uint64_t head) { |
|||
for (auto range : AllCases::instance().fetch()[head]) { |
|||
|
|||
test_func(RawCode::from_common_code(head << 32 | range).value()); |
|||
|
|||
} |
|||
}, head); |
|||
} |
|||
pool.wait_for_tasks(); |
|||
} |
@ -0,0 +1,137 @@ |
|||
#include "common.h" |
|||
#include "sample.h" |
|||
#include "raw_code.h" |
|||
#include "all_cases.h" |
|||
#include "common_code.h" |
|||
#include "gtest/gtest.h" |
|||
#include "BS_thread_pool.hpp" |
|||
|
|||
using klotski::range_reverse; |
|||
|
|||
using klotski::codec::RawCode; |
|||
using klotski::codec::CommonCode; |
|||
|
|||
using klotski::cases::AllCases; |
|||
using klotski::cases::ALL_CASES_NUM_; |
|||
|
|||
TEST(RawCode, validity) { |
|||
EXPECT_FALSE(RawCode::check(0x0A34'182B'3810'2D21)); // invalid code
|
|||
EXPECT_FALSE(RawCode::check(0x8603'EDF5'CAFF'F5E2)); // high 4-bits not zero
|
|||
|
|||
EXPECT_FALSE(RawCode::create(0x0000'0000'0000'0000).has_value()); // invalid code
|
|||
} |
|||
|
|||
TEST(RawCode, operators) { |
|||
auto raw_code = RawCode::unsafe_create(TEST_R_CODE); |
|||
|
|||
std::ostringstream tmp; |
|||
tmp << raw_code; // ostream capture
|
|||
EXPECT_TRUE(tmp.str().starts_with("603EDF5CAFFF5E2\n")); |
|||
EXPECT_EQ((uint64_t)raw_code, TEST_R_CODE); // convert as uint64_t
|
|||
|
|||
EXPECT_EQ(TEST_R_CODE, raw_code); // uint64_t == RawCode
|
|||
EXPECT_EQ(raw_code, TEST_R_CODE); // RawCode == uint64_t
|
|||
EXPECT_EQ(raw_code, raw_code); // RawCode == RawCode
|
|||
|
|||
EXPECT_NE(TEST_R_CODE + 1, raw_code); // uint64_t != RawCode
|
|||
EXPECT_NE(raw_code, TEST_R_CODE + 1); // RawCode != uint64_t
|
|||
EXPECT_NE(raw_code, RawCode::unsafe_create(TEST_R_CODE + 1)); // RawCode != RawCode
|
|||
} |
|||
|
|||
TEST(RawCode, exporter) { |
|||
auto raw_code = RawCode::unsafe_create(TEST_R_CODE); |
|||
EXPECT_EQ(raw_code.unwrap(), TEST_R_CODE); |
|||
EXPECT_EQ(raw_code.to_common_code(), TEST_C_CODE); |
|||
} |
|||
|
|||
TEST(RawCode, initializate) { |
|||
auto raw_code = RawCode::unsafe_create(TEST_R_CODE); |
|||
auto common_code = CommonCode::unsafe_create(TEST_C_CODE); |
|||
|
|||
// RawCode(...)
|
|||
EXPECT_EQ(RawCode(common_code), TEST_R_CODE); |
|||
EXPECT_EQ(RawCode(raw_code), TEST_R_CODE); // l-value
|
|||
EXPECT_EQ(RawCode(RawCode(raw_code)), TEST_R_CODE); // r-value
|
|||
|
|||
// RawCode::create(uint64_t)
|
|||
EXPECT_TRUE(RawCode::create(TEST_R_CODE).has_value()); |
|||
EXPECT_FALSE(RawCode::create(TEST_R_CODE_ERR).has_value()); |
|||
EXPECT_EQ(RawCode::create(TEST_R_CODE), TEST_R_CODE); |
|||
|
|||
// RawCode::unsafe_create(uint64_t)
|
|||
EXPECT_EQ(RawCode::unsafe_create(TEST_R_CODE), TEST_R_CODE); |
|||
|
|||
// RawCode::from_common_code(CommonCode)
|
|||
EXPECT_EQ(RawCode::from_common_code(common_code), TEST_R_CODE); |
|||
|
|||
// RawCode::from_common_code(uint64_t)
|
|||
EXPECT_TRUE(RawCode::from_common_code(TEST_C_CODE).has_value()); |
|||
EXPECT_FALSE(RawCode::from_common_code(TEST_C_CODE_ERR).has_value()); |
|||
EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE), TEST_R_CODE); |
|||
|
|||
// RawCode::from_common_code(const std::string &)
|
|||
EXPECT_TRUE(RawCode::from_common_code(TEST_C_CODE_STR).has_value()); |
|||
EXPECT_FALSE(RawCode::from_common_code(TEST_C_CODE_STR_ERR).has_value()); |
|||
EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE_STR), TEST_R_CODE); |
|||
|
|||
// RawCode::from_common_code(std::string &&)
|
|||
EXPECT_TRUE(RawCode::from_common_code(TEST_C_CODE_STR_RV).has_value()); |
|||
EXPECT_FALSE(RawCode::from_common_code(TEST_C_CODE_STR_ERR_RV).has_value()); |
|||
EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE_STR_RV), TEST_R_CODE); |
|||
} |
|||
|
|||
TEST(RawCode, code_verify) { |
|||
BS::thread_pool pool; |
|||
for (int head = 0; head < 16; ++head) { |
|||
pool.push_task([](uint64_t head) { |
|||
for (auto range : AllCases::instance().fetch()[head]) { |
|||
auto code = RawCode::from_common_code(head << 32 | range); |
|||
EXPECT_TRUE(code.has_value()); |
|||
EXPECT_TRUE(RawCode::check(code->unwrap())); |
|||
EXPECT_EQ(code->to_common_code(), head << 32 | range); |
|||
} |
|||
}, head); |
|||
} |
|||
pool.wait_for_tasks(); |
|||
} |
|||
|
|||
TEST(RawCode, DISABLED_global_verify) { |
|||
auto force_convert = [](uint64_t common_code) -> uint64_t { |
|||
auto range = range_reverse((uint32_t)common_code); |
|||
auto raw_code = K_MASK_2x2 << (common_code >> 32) * 3; |
|||
for (int addr = 0; range; range >>= 2) { |
|||
while ((raw_code >> addr) & 0b111 && addr < 60) // found next space
|
|||
addr += 3; |
|||
if (addr >= 60) // invalid address
|
|||
return 0; |
|||
switch (range & 0b11) { |
|||
case 0b01: raw_code |= K_MASK_1x2 << addr; break; |
|||
case 0b10: raw_code |= K_MASK_2x1 << addr; break; |
|||
case 0b11: raw_code |= K_MASK_1x1 << addr; break; |
|||
case 0b00: addr += 3; |
|||
} |
|||
} |
|||
return raw_code; |
|||
}; |
|||
|
|||
BS::thread_pool pool; |
|||
auto futures = pool.parallelize_loop(0x10'0000'0000, [&force_convert](uint64_t start, uint64_t end) { |
|||
std::vector<uint64_t> archive; |
|||
for (uint64_t common_code = start; common_code < end; ++common_code) { |
|||
if (RawCode::check(force_convert(common_code))) { |
|||
archive.emplace_back(common_code); // store valid raw code
|
|||
} |
|||
} |
|||
return archive; |
|||
}, 0x1000); // split as 4096 pieces
|
|||
|
|||
std::vector<uint64_t> result; |
|||
result.reserve(ALL_CASES_NUM_); |
|||
for (size_t i = 0; i < futures.size(); ++i) { |
|||
auto data = futures[i].get(); |
|||
std::cout << i << std::endl; |
|||
result.insert(result.end(), data.begin(), data.end()); // combine sections
|
|||
} |
|||
pool.wait_for_tasks(); |
|||
EXPECT_EQ(result, all_common_codes()); |
|||
} |
Loading…
Reference in new issue