Browse Source

feat: horizontal symmetry judgment of CommonCode

master
Dnomd343 1 week ago
parent
commit
1be78ec864
  1. 1
      src/core/CMakeLists.txt
  2. 23
      src/core/benchmark/codec.cc
  3. 8
      src/core/common_code/common_code.h
  4. 154
      src/core/common_code/internal/mirror.cc
  5. 24
      src/core/main.cc

1
src/core/CMakeLists.txt

@ -9,6 +9,7 @@ set(KLOTSKI_CORE_SRC
common_code/internal/common_code.cc
common_code/internal/serialize.cc
common_code/internal/mirror.cc
raw_code/internal/raw_code.cc
raw_code/internal/convert.cc

23
src/core/benchmark/codec.cc

@ -243,13 +243,32 @@ static void CommonCodeToShortCode(benchmark::State &state) {
}
}
static void IsMirrorCompare(benchmark::State &state) {
std::vector<CommonCode> samples;
for (auto common_code : common_code_samples(512)) {
samples.emplace_back(CommonCode::unsafe_create(common_code));
}
for (auto _ : state) {
for (auto code : samples) {
auto raw_code = code.to_raw_code();
volatile auto ret = raw_code.is_horizontal_mirror();
// volatile auto ret = CommonCode::is_mirror(code.unwrap());
}
}
}
// BENCHMARK(CommonCodeSerialize)->Range(8, 256);
// BENCHMARK(CommonCodeDeserialize)->Range(8, 256);
// BENCHMARK(CommonCodeSerializeShorten)->Range(8, 256);
// BENCHMARK(CommonCodeDeserializeShorten)->Range(8, 256);
BENCHMARK(ShortCodeSerialize)->Range(8, 256);
BENCHMARK(ShortCodeDeserialize)->Range(8, 256);
// BENCHMARK(ShortCodeSerialize)->Range(8, 256);
// BENCHMARK(ShortCodeDeserialize)->Range(8, 256);
BENCHMARK(IsMirrorCompare);
// BENCHMARK(ShortCodeToCommonCode);
// BENCHMARK(CommonCodeToShortCode);

8
src/core/common_code/common_code.h

@ -149,6 +149,8 @@ public:
// ------------------------------------------------------------------------------------- //
static bool is_mirror(uint64_t common_code);
private:
uint64_t code_;
@ -166,12 +168,6 @@ private:
// ------------------------------------------------------------------------------------- //
};
// Ref: https://cplusplus.github.io/CWG/issues/1734.html
// TODO: By definition, the default constructor is deleted, it is not trivial.
// TODO: But in clang and g++, it is legal, but in msvc it fails.
static_assert(std::is_trivial_v<CommonCode>);
static_assert(std::is_standard_layout_v<CommonCode>);
static_assert(std::is_trivially_copyable_v<CommonCode>);

154
src/core/common_code/internal/mirror.cc

@ -0,0 +1,154 @@
#include <iostream>
#include <format>
#include "common_code/common_code.h"
using klotski::codec::CommonCode;
bool CommonCode::is_mirror(uint64_t common_code) {
int head = common_code >> 32;
uint32_t ranges = range_reverse(common_code);
// std::cout << "head = " << head << std::endl;
// std::cout << "ranges = " << std::format("{:08X}", ranges) << std::endl;
if (head % 4 != 1) {
return false;
}
std::array<bool, 6> state {}; // mark emtry/half-full
if (head == 1) {
state.at(0) = true;
state.at(1) = true;
} else if (head == 5) {
state.at(1) = true;
state.at(2) = true;
} else if (head == 9) {
state.at(2) = true;
state.at(3) = true;
} else if (head == 13) {
state.at(3) = true;
state.at(4) = true;
}
int working_line = 0;
while (1 == 1) {
if (working_line > 4) {
// std::cout << "reach end line" << std::endl;
break;
}
// std::cout << std::endl;
// std::cout << "working_line: " << working_line << std::endl;
// std::cout << "state: " << std::format("{}", state) << std::endl;
if (!state.at(working_line)) { // empty line
// std::cout << "empty working line" << std::endl;
/// simple single line
bool is_single_line = false;
if ((ranges & 0b1111) == 0b0101) {
ranges >>= 4;
is_single_line = true;
} else {
auto tmp = ranges & 0b111111;
if (tmp == 0b110111 || tmp == 0b000100) {
ranges >>= 6;
is_single_line = true;
} else {
auto tmp_ = ranges & 0b11111111;
if (tmp_ == 0b00000000 || tmp_ == 0b11111111 || tmp_ == 0b00111100 || tmp_ == 0b11000011) {
ranges >>= 8;
is_single_line = true;
}
}
}
if (is_single_line) {
// std::cout << "simple single line" << std::endl;
++working_line; // next line
continue;
}
/// half-double line
bool is_half_double_line = false;
if ((ranges & 0b111111) == 0b100110) {
ranges >>= 6;
is_half_double_line = true;
} else {
auto tmp = ranges & 0b11111111;
if (tmp == 0b10111110 || tmp == 0b11101011 || tmp == 0b00101000 || tmp == 0b10000010) {
ranges >>= 8;
is_half_double_line = true;
}
}
if (is_half_double_line) {
// std::cout << "half double line" << std::endl;
if (state.at(working_line + 1)) {
working_line += 2; // next 2 lines
} else {
state.at(working_line + 1) = true;
++working_line; // next line
}
continue;
}
/// full-double line
if ((ranges & 0b11111111) == 0b10101010) {
// std::cout << "full double line" << std::endl;
ranges >>= 8;
working_line += 2;
continue;
}
// std::cout << "not mirror layout" << std::endl;
return false;
} else { // half-full line
// std::cout << "half-full working line" << std::endl;
/// simple single line
bool is_simple_line = false;
if ((ranges & 0b11) == 0b01) {
ranges >>= 2;
is_simple_line = true;
} else {
auto tmp = ranges & 0b1111;
if (tmp == 0b0000 || tmp == 0b1111) {
ranges >>= 4;
is_simple_line = true;
}
}
if (is_simple_line) {
// std::cout << "simple single line" << std::endl;
++working_line;
continue;
}
/// half-double line
if ((ranges & 0b1111) == 0b1010) {
// std::cout << "half double line" << std::endl;
ranges >>= 4;
if (state.at(working_line + 1)) {
working_line += 2; // next 2 lines
} else {
state.at(working_line + 1) = true;
++working_line; // next line
}
continue;
}
// std::cout << "not mirror layout" << std::endl;
return false;
}
}
return true;
}

24
src/core/main.cc

@ -40,7 +40,29 @@ int main() {
const auto start = std::chrono::system_clock::now();
GroupCases::from_info_t({169, 1, 7472});
// auto ret = CommonCode::is_mirror(0x1A9BF0C00);
// auto ret = CommonCode::is_mirror(0x4FEA13400);
// auto ret = CommonCode::is_mirror(0x100AA0300);
// auto ret = CommonCode::is_mirror(0x5000A0000);
// std::cout << "ret = " << ret << std::endl;
// auto raw_code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code();
// std::cout << raw_code.is_horizontal_mirror() << std::endl;
// for (auto common_code : AllCases::instance().fetch().codes()) {
// auto raw_code = common_code.to_raw_code();
//
// bool r1 = raw_code.is_horizontal_mirror();
// bool r2 = CommonCode::is_mirror(common_code.unwrap());
//
// if (r1 != r2) {
// std::cout << "found invalid" << std::endl;
// std::cout << common_code << std::endl;
// break;
// }
// }
// GroupCases::from_info_t({169, 1, 7472});
// GroupCases::to_info_t(CommonCode::unsafe_create(0x1A9BF0C00).to_short_code());

Loading…
Cancel
Save