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 "utils/utility.h"
|
||||
#include "ranges/ranges.h" |
// #include "ranges/ranges.h"
|
||||
|
//
|
||||
using klotski::cases::Ranges; |
// 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
|
|
||||
} |
|
||||
} |
|
||||
|
@ -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