mirror of https://github.com/dnomd343/klotski.git
Dnomd343
7 months ago
15 changed files with 258 additions and 301 deletions
@ -0,0 +1,57 @@ |
|||||
|
#include "utils/utility.h" |
||||
|
#include "ranges/ranges.h" |
||||
|
|
||||
|
/// Check whether the combination of head and range is valid.
|
||||
|
static int check_range(const int head, uint32_t range) noexcept { |
||||
|
constexpr uint32_t M_1x1 = 0b00000001; |
||||
|
constexpr uint32_t M_1x2 = 0b00000011; |
||||
|
constexpr uint32_t M_2x1 = 0b00010001; |
||||
|
constexpr uint32_t M_2x2 = 0b00110011; |
||||
|
|
||||
|
uint32_t flags = M_2x2 << head; // fill 2x2 block
|
||||
|
for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit
|
||||
|
const auto num = klotski::low_zero_num(~flags); |
||||
|
addr += num; // next unfilled block
|
||||
|
flags >>= num; |
||||
|
switch (range & 0b11) { |
||||
|
case 0b00: // space
|
||||
|
case 0b11: // 1x1 block
|
||||
|
flags |= M_1x1; |
||||
|
continue; |
||||
|
case 0b10: // 2x1 block
|
||||
|
if ((flags >> 4) & 0b1 || addr > 15) { // invalid case
|
||||
|
return offset; // broken offset
|
||||
|
} |
||||
|
flags |= M_2x1; |
||||
|
continue; |
||||
|
case 0b01: // 1x2 block
|
||||
|
if ((flags >> 1) & 0b1 || (addr & 0b11) == 0b11) { // invalid case
|
||||
|
return offset; // broken offset
|
||||
|
} |
||||
|
flags |= M_1x2; |
||||
|
continue; |
||||
|
} |
||||
|
} |
||||
|
return 0; // pass check
|
||||
|
} |
||||
|
|
||||
|
void klotski::cases::Ranges::with_head(const int head, Ranges &release) const { |
||||
|
// release.clear();
|
||||
|
// release.reserve(ALL_CASES_NUM[head]);
|
||||
|
// auto &basic_ranges = BasicRanges::instance().fetch();
|
||||
|
|
||||
|
for (uint32_t index = 0; index < ranges_.size(); ++index) { |
||||
|
auto offset = check_range(head, ranges_[index]); |
||||
|
if (offset) { // invalid case
|
||||
|
auto tmp = (uint32_t)0b1 << (32 - offset * 2); // distance to next possible range
|
||||
|
/// !! <- broken
|
||||
|
/// ( xx xx xx ) xx xx xx ... [reversed range]
|
||||
|
/// +1 00 00 00 ... (delta)
|
||||
|
tmp += klotski::range_reverse(ranges_[index]) & ~(tmp - 1); |
||||
|
while (klotski::range_reverse(ranges_[++index]) < tmp); // located next range
|
||||
|
--index; |
||||
|
continue; |
||||
|
} |
||||
|
release.ranges_.emplace_back(klotski::range_reverse(ranges_[index])); // release valid case
|
||||
|
} |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
#include <list> |
||||
|
#include <algorithm> |
||||
|
|
||||
|
#include "ranges/ranges.h" |
||||
|
#include "utils/utility.h" |
||||
|
|
||||
|
template<int N> |
||||
|
static void demo(std::vector<uint32_t> &ranges, int n_10, int n_11) { |
||||
|
|
||||
|
constexpr auto num = 16 - N; |
||||
|
constexpr auto offset = (16 - num) << 1; // offset of low bits
|
||||
|
|
||||
|
int n_00 = 16 - N * 2 - n_11; |
||||
|
int n_01 = N - n_10; |
||||
|
|
||||
|
std::array<int, num> series {}; |
||||
|
|
||||
|
auto kk = std::fill_n(series.begin() + n_00, n_01, 0b01); |
||||
|
auto pp = std::fill_n(kk, n_10, 0b10); |
||||
|
std::fill_n(pp, n_11, 0b11); |
||||
|
|
||||
|
// std::vector<uint32_t> ranges;
|
||||
|
|
||||
|
do { |
||||
|
uint32_t range = 0; |
||||
|
for (const auto x : series) // store every 2-bit
|
||||
|
(range <<= 2) |= x; |
||||
|
ranges.emplace_back(range << offset); |
||||
|
} while (std::ranges::next_permutation(series).found); |
||||
|
|
||||
|
// return ranges;
|
||||
|
} |
||||
|
|
||||
|
// void klotski::cases::spawn_ranges(std::vector<uint32_t> &ranges, int n, int n_2x1, int n_1x1) {
|
||||
|
//
|
||||
|
//
|
||||
|
// }
|
||||
|
|
||||
|
void klotski::cases::Ranges::spawn_more(int n, int n_2x1, int n_1x1) { |
||||
|
// spawn_ranges(ranges_, n, n_2x1, n_1x1);
|
||||
|
|
||||
|
switch (n) { |
||||
|
case 0: return demo<0>(ranges_, n_2x1, n_1x1); |
||||
|
case 1: return demo<1>(ranges_, n_2x1, n_1x1); |
||||
|
case 2: return demo<2>(ranges_, n_2x1, n_1x1); |
||||
|
case 3: return demo<3>(ranges_, n_2x1, n_1x1); |
||||
|
case 4: return demo<4>(ranges_, n_2x1, n_1x1); |
||||
|
case 5: return demo<5>(ranges_, n_2x1, n_1x1); |
||||
|
case 6: return demo<6>(ranges_, n_2x1, n_1x1); |
||||
|
case 7: return demo<7>(ranges_, n_2x1, n_1x1); |
||||
|
default: return; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <vector> |
||||
|
#include <cstdint> |
||||
|
|
||||
|
#include "utils/utility.h" |
||||
|
|
||||
|
namespace klotski::cases { |
||||
|
|
||||
|
// void spawn_ranges(std::vector<uint32_t> &ranges, int n, int n_2x1, int n_1x1);
|
||||
|
|
||||
|
// std::vector<uint32_t> basic_ranges();
|
||||
|
|
||||
|
// TODO: should we inherit on `std::vector<uint32_t>` ?
|
||||
|
class Ranges { |
||||
|
public: |
||||
|
void spawn_more(int n, int n_2x1, int n_1x1); |
||||
|
|
||||
|
using iterator = std::vector<uint32_t>::iterator; |
||||
|
using size_type = std::vector<uint32_t>::size_type; |
||||
|
using const_iterator = std::vector<uint32_t>::const_iterator; |
||||
|
|
||||
|
using value_type = std::vector<uint32_t>::value_type; |
||||
|
|
||||
|
using reference = std::vector<uint32_t>::reference; |
||||
|
|
||||
|
using const_reference = std::vector<uint32_t>::const_reference; |
||||
|
|
||||
|
iterator begin() { |
||||
|
return ranges_.begin(); |
||||
|
} |
||||
|
|
||||
|
iterator end() { |
||||
|
return ranges_.end(); |
||||
|
} |
||||
|
|
||||
|
[[nodiscard]] const_iterator begin() const { |
||||
|
return ranges_.begin(); |
||||
|
} |
||||
|
|
||||
|
[[nodiscard]] const_iterator end() const { |
||||
|
return ranges_.end(); |
||||
|
} |
||||
|
|
||||
|
void clear() { |
||||
|
ranges_.clear(); |
||||
|
} |
||||
|
|
||||
|
[[nodiscard]] size_type size() const { |
||||
|
return ranges_.size(); |
||||
|
} |
||||
|
|
||||
|
void reserve(const size_type cap) { |
||||
|
ranges_.reserve(cap); |
||||
|
} |
||||
|
|
||||
|
void with_head(int head, Ranges &release) const; |
||||
|
|
||||
|
void reverse() { |
||||
|
for (auto &x : ranges_) { |
||||
|
x = range_reverse(x); // flip every 2-bit
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const_reference operator[](const size_type n) const { |
||||
|
return ranges_[n]; |
||||
|
} |
||||
|
|
||||
|
[[nodiscard]] const value_type* data() const { |
||||
|
return ranges_.data(); |
||||
|
} |
||||
|
|
||||
|
// private:
|
||||
|
std::vector<uint32_t> ranges_ {}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace klotski::cases
|
Loading…
Reference in new issue