mirror of https://github.com/dnomd343/klotski.git
Dnomd343
1 month ago
12 changed files with 129 additions and 84 deletions
@ -0,0 +1,9 @@ |
|||
/// Klotski Engine by Dnomd343 @2024
|
|||
|
|||
#pragma once |
|||
|
|||
namespace klotski::codec { |
|||
|
|||
class CommonCode; |
|||
|
|||
} // namespace klotski::codec
|
@ -0,0 +1,33 @@ |
|||
#pragma once |
|||
|
|||
namespace klotski::cases { |
|||
|
|||
KLSK_INLINE_CE int Ranges::check(const int head, uint32_t range) { |
|||
KLSK_ASSUME(head >= 0 && head < 16 && head % 4 != 3); |
|||
uint32_t flags = 0b110011 << head; // fill 2x2 block |
|||
for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit |
|||
const auto num = std::countr_one(flags); |
|||
addr += num; // next unfilled block |
|||
flags >>= num; |
|||
switch (range & 0b11) { |
|||
case 0b00: // space |
|||
case 0b11: // 1x1 block |
|||
flags |= 0b1; |
|||
continue; |
|||
case 0b01: // 1x2 block |
|||
if (flags & 0b10 || addr % 4 == 3) { // invalid case |
|||
return offset; // broken offset |
|||
} |
|||
flags |= 0b11; |
|||
continue; |
|||
case 0b10: // 2x1 block |
|||
if (flags & 0b10000 || addr > 15) { // invalid case |
|||
return offset; // broken offset |
|||
} |
|||
flags |= 0b10001; |
|||
} |
|||
} |
|||
return 0; // pass check |
|||
} |
|||
|
|||
} // namespace klotski::cases |
@ -1,52 +1,4 @@ |
|||
#include "utils/utility.h" |
|||
#include "ranges/ranges.h" |
|||
|
|||
using klotski::cases::Ranges; |
|||
|
|||
int Ranges::check(const int head, uint32_t range) { |
|||
KLSK_ASSUME(head >= 0 && head < 16 && head % 4 != 3); |
|||
uint32_t flags = 0b110011 << head; // fill 2x2 block
|
|||
for (int addr = 0, offset = 1; range; range >>= 2, ++offset) { // traverse every 2-bit
|
|||
const auto num = std::countr_one(flags); |
|||
addr += num; // next unfilled block
|
|||
flags >>= num; |
|||
switch (range & 0b11) { |
|||
case 0b00: // space
|
|||
case 0b11: // 1x1 block
|
|||
flags |= 0b1; |
|||
continue; |
|||
case 0b01: // 1x2 block
|
|||
if (flags & 0b10 || addr % 4 == 3) { // invalid case
|
|||
return offset; // broken offset
|
|||
} |
|||
flags |= 0b11; |
|||
continue; |
|||
case 0b10: // 2x1 block
|
|||
if (flags & 0b10000 || addr > 15) { // invalid case
|
|||
return offset; // broken offset
|
|||
} |
|||
flags |= 0b10001; |
|||
} |
|||
} |
|||
return 0; // pass check
|
|||
} |
|||
|
|||
void Ranges::derive(const int head, Ranges &output) const { |
|||
const uint32_t max_val = range_reverse(this->back()); |
|||
for (uint32_t index = 0; index < size(); ++index) { |
|||
if (const auto offset = check(head, (*this)[index])) { // invalid case
|
|||
/// !! <- broken
|
|||
/// ( xx xx xx ) xx xx xx ... [reversed range]
|
|||
/// +1 00 00 00 ... (delta)
|
|||
const uint32_t delta = 1U << (32 - offset * 2); // distance to next possible range
|
|||
const auto min_next = delta + (range_reverse((*this)[index]) & ~(delta - 1)); |
|||
if (min_next > max_val) { |
|||
break; // index has overflowed
|
|||
} |
|||
while (range_reverse((*this)[++index]) < min_next) {} // located next range
|
|||
--index; |
|||
continue; |
|||
} |
|||
output.emplace_back(range_reverse((*this)[index])); // release valid case
|
|||
} |
|||
} |
|||
// #include "utils/utility.h"
|
|||
// #include "ranges/ranges.h"
|
|||
//
|
|||
// using klotski::cases::Ranges;
|
|||
|
@ -0,0 +1,10 @@ |
|||
/// Klotski Engine by Dnomd343 @2024
|
|||
|
|||
#pragma once |
|||
|
|||
namespace klotski::cases { |
|||
|
|||
class Ranges; |
|||
class RangesUnion; |
|||
|
|||
} // namespace klotski::cases
|
Loading…
Reference in new issue