Browse Source

update: enhance basic ranges build

master
Dnomd343 10 months ago
parent
commit
bad13867cd
  1. 284
      src/core/all_cases/basic_ranges.cc
  2. 78
      src/core/all_cases/basic_ranges.h

284
src/core/all_cases/basic_ranges.cc

@ -1,157 +1,64 @@
#include <iostream>
#include <vector>
#include <list> #include <list>
#include <vector>
#include <algorithm> #include <algorithm>
#include "basic_ranges.h"
static uint32_t range_reverse(uint32_t bin) noexcept {
// bin = ((bin << 16) & 0xFFFF0000) | ((bin >> 16) & 0x0000FFFF);
// bin = ((bin << 8) & 0xFF00FF00) | ((bin >> 8) & 0x00FF00FF);
bin = __builtin_bswap32(bin);
bin = ((bin << 4) & 0xF0F0F0F0) | ((bin >> 4) & 0x0F0F0F0F);
return ((bin << 2) & 0xCCCCCCCC) | ((bin >> 2) & 0x33333333);
}
void build(std::vector<uint32_t> &result, int n1, int n2, int n3, int n4) { #include "basic_ranges.h"
std::vector<int> demo; #include <iostream>
demo.reserve(n1 + n2 + n3 + n4);
int move_num = 32 - (n1 + n2 + n3 + n4) * 2; typedef uint32_t Range;
typedef std::vector<Range> Ranges;
typedef std::vector<Range>::iterator RangeIter;
typedef std::tuple<int, int, int, int> RangeType;
demo.insert(demo.end(), n1, 0b00); static const auto RangeTypeNum = 204;
demo.insert(demo.end(), n2, 0b01);
demo.insert(demo.end(), n3, 0b10);
demo.insert(demo.end(), n4, 0b11);
// for (int i = 0; i < n1; ++i) { static const uint32_t BASIC_RANGES_NUM = 7311921;
// demo.emplace_back(0b00);
// }
// for (int i = 0; i < n2; ++i) {
// demo.emplace_back(0b01);
// }
// for (int i = 0; i < n3; ++i) {
// demo.emplace_back(0b10);
// }
// for (int i = 0; i < n4; ++i) {
// demo.emplace_back(0b11);
// }
// for (auto x : demo) { class BasicRanges {
// std::cout << x << " "; public:
// } static void build_ranges();
// std::cout << std::endl;
do { static const Ranges& fetch();
uint32_t tmp = 0; private:
for (auto x : demo) { static Ranges data_;
tmp <<= 2;
tmp |= x;
}
tmp <<= move_num;
// volatile auto r = tmp;
result.emplace_back(tmp);
} while (next_permutation(demo.begin(), demo.end())); static void spawn_ranges(int, int, int, int);
} };
template <class T>
void sort(T begin, T end, T kk) {
std::vector<uint32_t> tmp;
tmp.reserve(end - begin);
auto k1 = begin;
auto k2 = kk;
while (1 == 1) {
if (*k1 < *k2) {
tmp.emplace_back(*k1);
++k1;
if (k1 == kk) {
tmp.insert(tmp.end(), k2, end);
break;
}
} else {
tmp.emplace_back(*k2);
++k2;
if (k2 == end) {
tmp.insert(tmp.end(), k1, kk);
break;
}
}
}
auto p = begin; Ranges BasicRanges::data_;
for (auto x : tmp) {
*p = x;
++p;
}
static Range range_reverse(Range bin) noexcept {
#if defined(__GNUC__) || defined(__clang__)
bin = __builtin_bswap32(bin);
// TODO: using `std::byteswap` (c++23)
#else
// FIXME: `_byteswap_ulong` under MSVC
bin = ((bin << 16) & 0xFFFF0000) | ((bin >> 16) & 0x0000FFFF);
bin = ((bin << 8) & 0xFF00FF00) | ((bin >> 8) & 0x00FF00FF);
#endif
bin = ((bin << 4) & 0xF0F0F0F0) | ((bin >> 4) & 0x0F0F0F0F);
return ((bin << 2) & 0xCCCCCCCC) | ((bin >> 2) & 0x33333333);
} }
template<class ITER_T> consteval static std::array<RangeType, RangeTypeNum> basic_types() {
void sort_v2(ITER_T begin, ITER_T end, ITER_T mid) { std::array<RangeType, RangeTypeNum> data;
for (int i = 0, n = 0; n <= 7; ++n) // number of 1x2 and 2x1 block -> 0 ~ 7
std::vector<uint32_t> tmp {begin, mid}; for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) // number of 2x1 block -> 0 ~ n
auto k1 = tmp.begin(); for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) // number of 1x1 block -> 0 ~ (14 - 2n)
auto k2 = mid; data[i++] = {16 - n * 2 - n_1x1, n - n_2x1, n_2x1, n_1x1};
auto target = begin; return data;
while (1 == 1) {
// std::cout << *k1 << " vs " << *k2 << std::endl;
if (*k1 < *k2) {
*target = *k1;
++target;
// tmp.emplace_back(*k1);
++k1;
if (k1 == tmp.end()) {
// memcpy(&*target, &*k2, end - k2);
// tmp.insert(tmp.end(), k2, end);
break;
}
} else {
*target = *k2;
++target;
// tmp.emplace_back(*k2);
++k2;
if (k2 == end) {
// std::cout << "get it" << std::endl;
// std::cout << "size = " << (tmp.end() - k1) << std::endl;
// std::cout << (target - begin)
memcpy(&*target, &*k1, (tmp.end() - k1) * 4);
// tmp.insert(tmp.end(), k1, kk);
break;
}
}
}
//
// auto p = begin;
// for (auto x : tmp) {
// *p = x;
// ++p;
// }
} }
template<class ITER_T> static void combine_sort(RangeIter begin, RangeIter mid, RangeIter end) {
void sort_v3(ITER_T begin, ITER_T end, ITER_T mid) { Ranges tmp = {begin, mid};
std::vector<uint32_t> tmp = {begin, mid};
auto p = tmp.begin(); auto p = tmp.begin();
for (;;) { for (;;) {
if (*p < *mid) { if (*p < *mid) {
*(begin++) = *(p++); *(begin++) = *(p++);
if (p == tmp.end()) { if (p == tmp.end())
return; return;
}
} else { } else {
*(begin++) = *(mid++); *(begin++) = *(mid++);
if (mid == end) { if (mid == end) {
@ -162,88 +69,53 @@ void sort_v3(ITER_T begin, ITER_T end, ITER_T mid) {
} }
} }
void demo() { void BasicRanges::spawn_ranges(int n1, int n2, int n3, int n4) {
std::vector<int> series;
// std::vector<uint32_t> demo = {1, 2, 5, 9, 11, 3, 6, 7}; auto n = n1 + n2 + n3 + n4;
// auto kk = demo.begin() + 5; auto offset = (16 - n) << 1;
// for (auto p = demo.begin(); p < kk; ++p) { series.insert(series.end(), n1, 0b00);
// std::cout << *p << std::endl; series.insert(series.end(), n2, 0b01);
// } series.insert(series.end(), n3, 0b10);
// sort_v3(demo.begin(), demo.end(), kk); series.insert(series.end(), n4, 0b11);
//
// for (auto x : demo) {
// std::cout << x << std::endl;
// }
// return;
// uint32_t tmp = 0x5129B263; // 0xC98E6845
//
// for (uint64_t i = 0; i < 0xFFFFFFFF; ++i) {
// volatile auto r = range_reverse(tmp);
// }
// printf("%08X\n", tmp);
std::vector<uint32_t> result;
result.reserve(7311921);
// build(result, 4, 2, 1, 6);
std::list<decltype(result.begin())> pp;
pp.emplace_back(result.begin());
for (int n = 0; n <= 7; ++n) // number of 1x2 and 2x1 block -> 0 ~ 7
for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) // number of 2x1 block -> 0 ~ n
for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block -> 0 ~ (14 - 2n)
build(result, 16 - n * 2 - n_1x1, n - n_2x1, n_2x1, n_1x1);
pp.emplace_back(result.end());
}
// std::stable_sort(result.begin(), result.end()); do {
// return; uint32_t range = 0;
for (auto x : series)
(range <<= 2) |= x;
data_.emplace_back(range << offset);
} while (next_permutation(series.begin(), series.end()));
}
// sort(result.begin() + 363149, result.begin() + 459674, result.begin() + 408194); void BasicRanges::build_ranges() {
data_.reserve(BASIC_RANGES_NUM);
std::list<RangeIter> flags {data_.begin()};
while (1 == 1) { for (auto &t : basic_types()) {
auto begin = pp.begin(); spawn_ranges(std::get<0>(t), std::get<1>(t), std::get<2>(t), std::get<3>(t));
while (1 == 1) { flags.emplace_back(data_.end());
auto mid = begin;
++mid;
if (mid == pp.end()) {
break;
}
auto end = mid;
++end;
if (end == pp.end()) {
break;
}
// std::cout << (*begin - result.begin()) << " " << (*mid - result.begin()) << " " << (*end - result.begin()) << std::endl;
sort_v3(*begin, *end, *mid);
++begin;
++begin;
pp.erase(mid);
}
if (pp.size() == 2) {
break;
}
} }
do {
std::list<RangeIter>::iterator begin = flags.begin(), mid, end;
while (++(mid = begin) != flags.end() && ++(end = mid) != flags.end()) {
combine_sort(*begin, *mid, *end);
flags.erase(mid);
begin = end;
}
} while (flags.size() > 2);
for (auto &x : data_) {
// std::sort(result.begin(), result.end());
// std::stable_sort(result.begin(), result.end());
for (auto &x : result) {
x = range_reverse(x); x = range_reverse(x);
} }
}
for (auto x : result) { const Ranges& BasicRanges::fetch() {
printf("%08X\n", x); return data_;
} }
// for (uint32_t i = 0; i < 0xFF; ++i) { void demo() {
// build(result, 4, 2, 1, 6); BasicRanges::build_ranges();
// }
for (auto x : BasicRanges::fetch()) {
printf("%08X\n", x);
}
} }

78
src/core/all_cases/basic_ranges.h

@ -37,44 +37,44 @@ namespace klotski {
/// basic ranges count /// basic ranges count
const uint32_t BASIC_RANGES_SIZE = 7311921; const uint32_t BASIC_RANGES_SIZE = 7311921;
class BasicRanges { // class BasicRanges {
public: // public:
/// Three basic states, one-way transition. // /// Three basic states, one-way transition.
/// {NOT_INIT} -> {BUILDING} -> {AVAILABLE} // /// {NOT_INIT} -> {BUILDING} -> {AVAILABLE}
enum Status { // enum Status {
NOT_INIT, // NOT_INIT,
BUILDING, // BUILDING,
AVAILABLE, // AVAILABLE,
}; // };
typedef std::vector<uint32_t> basic_ranges_t; // typedef std::vector<uint32_t> basic_ranges_t;
//
/// Trigger the build process, from `NOT_INIT` to `BUILDING`. // /// Trigger the build process, from `NOT_INIT` to `BUILDING`.
static void build(); // static void build();
//
/// Get current status of BasicRanges. // /// Get current status of BasicRanges.
static Status status() noexcept; // static Status status() noexcept;
//
/// Blocking access to constructed data. // /// Blocking access to constructed data.
static const basic_ranges_t& fetch(); // static const basic_ranges_t& fetch();
//
private: // private:
static bool available_; // static bool available_;
static std::mutex building_; // static std::mutex building_;
static basic_ranges_t data_; // static basic_ranges_t data_;
//
static void build_data(); // static void build_data();
//
public: // public:
/// The number of types of blocks. // /// The number of types of blocks.
struct generate_t { // struct generate_t {
int n1; // number of `00` -> space // int n1; // number of `00` -> space
int n2; // number of `01` -> 1x2 block // int n2; // number of `01` -> 1x2 block
int n3; // number of `10` -> 2x1 block // int n3; // number of `10` -> 2x1 block
int n4; // number of `11` -> 1x1 block // int n4; // number of `11` -> 1x1 block
}; // };
//
/// Generate all basic-ranges of the specified type. // /// Generate all basic-ranges of the specified type.
static void generate(basic_ranges_t &release, generate_t info); // static void generate(basic_ranges_t &release, generate_t info);
}; // };
} // namespace klotski } // namespace klotski

Loading…
Cancel
Save