|
|
@ -1,51 +1,64 @@ |
|
|
|
#include <gtest/gtest.h> |
|
|
|
|
|
|
|
#include "helper/cases.h" |
|
|
|
#include "group/group.h" |
|
|
|
#include "ranges/ranges.h" |
|
|
|
|
|
|
|
#include "helper/expect.h" |
|
|
|
#include "helper/parallel.h" |
|
|
|
#include "helper/block_num.h" |
|
|
|
|
|
|
|
#include "group/group.h" |
|
|
|
#include "ranges/ranges.h" |
|
|
|
using klotski::cases::Ranges; |
|
|
|
using klotski::cases::AllCases; |
|
|
|
using klotski::codec::CommonCode; |
|
|
|
using klotski::cases::BasicRanges; |
|
|
|
using klotski::cases::RangesUnion; |
|
|
|
|
|
|
|
using klotski::range_reverse; |
|
|
|
using klotski::group::BLOCK_NUM; |
|
|
|
using klotski::cases::ALL_CASES_NUM; |
|
|
|
using klotski::cases::BASIC_RANGES_NUM_; |
|
|
|
|
|
|
|
constexpr auto Heads = RangesUnion::Heads; |
|
|
|
|
|
|
|
static_assert(std::is_base_of_v<std::vector<uint32_t>, Ranges>); |
|
|
|
|
|
|
|
TEST(Ranges, check) { |
|
|
|
RangesUnion all_cases; |
|
|
|
for (const auto head : Heads) { |
|
|
|
for (auto range : BasicRanges::instance().fetch()) { |
|
|
|
if (Ranges::check(head, range_reverse(range)) == 0) { |
|
|
|
all_cases.ranges(head).emplace_back(range); // found valid cases
|
|
|
|
HEAD_PARALLEL({ |
|
|
|
Ranges cases; |
|
|
|
cases.reserve(ALL_CASES_NUM[head]); |
|
|
|
for (const auto range : BasicRanges::instance().fetch()) { |
|
|
|
if (Ranges::check(static_cast<int>(head), range_reverse(range)) == 0) { |
|
|
|
cases.emplace_back(range); // found valid cases
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
EXPECT_EQ(all_cases, AllCases::instance().fetch()); |
|
|
|
EXPECT_EQ(cases, AllCases::instance().fetch().ranges(head)); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
TEST(Ranges, spawn) { |
|
|
|
for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) { |
|
|
|
BLOCK_NUM_PARALLEL({ |
|
|
|
Ranges ranges; |
|
|
|
ranges.spawn(n, n_2x1, n_1x1); |
|
|
|
EXPECT_SORTED_AND_UNIQUE(ranges); // sorted and unique
|
|
|
|
|
|
|
|
for (const auto range : ranges) { |
|
|
|
const auto [val_1x1, val_1x2, val_2x1] = helper::cal_block_num(range); |
|
|
|
EXPECT_EQ(val_1x1, n_1x1); |
|
|
|
EXPECT_EQ(val_2x1, n_2x1); |
|
|
|
EXPECT_EQ(val_1x2 + val_2x1, n); // verify block nums
|
|
|
|
const auto val = helper::cal_block_num(range); |
|
|
|
EXPECT_EQ(n_1x1, val.n_1x1); |
|
|
|
EXPECT_EQ(n_2x1, val.n_2x1); |
|
|
|
EXPECT_EQ(n, val.n_1x2 + val.n_2x1); // verify block nums
|
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
TEST(Ranges, derive) { |
|
|
|
for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) { |
|
|
|
BLOCK_NUM_PARALLEL({ |
|
|
|
Ranges ranges; |
|
|
|
ranges.spawn(n, n_2x1, n_1x1); |
|
|
|
ranges.reverse(); // reverse ranges for derive
|
|
|
|
|
|
|
|
RangesUnion cases; |
|
|
|
for (const auto head : Heads) { |
|
|
|
ranges.derive(head, cases.ranges(head)); |
|
|
|
ranges.derive(static_cast<int>(head), cases.ranges(head)); |
|
|
|
EXPECT_SORTED_AND_UNIQUE(cases.ranges(head)); // sorted and unique
|
|
|
|
EXPECT_COMMON_CODES(head, cases.ranges(head)); // verify common codes
|
|
|
|
} |
|
|
@ -54,7 +67,7 @@ TEST(Ranges, derive) { |
|
|
|
for (const auto head : Heads) { |
|
|
|
EXPECT_SUBSET(ranges, cases.ranges(head)); // derive ranges is subset
|
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
TEST(Ranges, append) { |
|
|
@ -65,13 +78,15 @@ TEST(Ranges, append) { |
|
|
|
auto &tmp = ranges += r; |
|
|
|
EXPECT_EQ(tmp, ranges); // reference of ranges
|
|
|
|
} |
|
|
|
std::stable_sort(ranges.begin(), ranges.end()); |
|
|
|
std::ranges::stable_sort(ranges.begin(), ranges.end()); |
|
|
|
EXPECT_EQ(ranges, BasicRanges::instance().fetch()); |
|
|
|
} |
|
|
|
|
|
|
|
TEST(Ranges, reverse) { |
|
|
|
auto ranges = BasicRanges::instance().fetch(); |
|
|
|
auto reverse = ranges | std::views::transform(range_reverse) | std::ranges::to<std::vector>(); |
|
|
|
const auto reverse = ranges |
|
|
|
| std::views::transform(range_reverse) |
|
|
|
| std::ranges::to<std::vector>(); |
|
|
|
ranges.reverse(); |
|
|
|
EXPECT_EQ(ranges, reverse); |
|
|
|
ranges.reverse(); |
|
|
@ -91,8 +106,8 @@ TEST(Ranges, combine) { |
|
|
|
ranges.spawn(n, n_2x1, n_1x1); |
|
|
|
all_ranges += ranges; |
|
|
|
ranges.reverse(); // reverse ranges for derive
|
|
|
|
for (const auto head : Heads) { |
|
|
|
ranges.derive(head, all_cases.ranges(head)); // derive from sub ranges
|
|
|
|
for (const auto head : Heads) { // derive from sub ranges
|
|
|
|
ranges.derive(static_cast<int>(head), all_cases.ranges(head)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -104,9 +119,17 @@ TEST(Ranges, combine) { |
|
|
|
EXPECT_EQ(all_cases, AllCases::instance().fetch()); // verify all cases
|
|
|
|
|
|
|
|
all_ranges.reverse(); // reverse ranges for derive
|
|
|
|
for (const auto head : Heads) { |
|
|
|
for (const auto head : Heads) { // derive from all ranges
|
|
|
|
all_cases.ranges(head).clear(); |
|
|
|
all_ranges.derive(head, all_cases.ranges(head)); // derive from all ranges
|
|
|
|
all_ranges.derive(static_cast<int>(head), all_cases.ranges(head)); |
|
|
|
} |
|
|
|
EXPECT_EQ(all_cases, AllCases::instance().fetch()); // verify content
|
|
|
|
} |
|
|
|
|
|
|
|
TEST(Ranges, constexpr) { |
|
|
|
static_assert(Ranges::check(1, 0x0030FE6A) == 0); |
|
|
|
static_assert(Ranges::check(4, 0x001C4ABF) == 0); |
|
|
|
|
|
|
|
static_assert(Ranges::check(1, 0xA9BF0C00) == 14); |
|
|
|
static_assert(Ranges::check(4, 0xFEA13400) == 6); |
|
|
|
} |
|
|
|