Browse Source

update: test raw code and compact code

legacy
dnomd343 2 years ago
parent
commit
1bb7b6f10c
  1. 2
      CMakeLists.txt
  2. 139
      case.cc
  3. 9
      case.h
  4. 31
      common.cc
  5. 10
      common.h
  6. BIN
      klotski
  7. 55
      klotski.cc
  8. 73
      klotski.h
  9. 84
      main.cc
  10. 195
      main.cpp

2
CMakeLists.txt

@ -3,4 +3,4 @@ project(klotski)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
add_executable(klotski main.cpp) add_executable(klotski main.cc case.cc common.cc klotski.cc)

139
case.cpp → case.cc

@ -1,66 +1,43 @@
#include <cstdio> #include "case.h"
#include <vector> #include "common.h"
#include <algorithm> #include <algorithm>
typedef __uint32_t uint32_t; bool check_case(int head, uint32_t range);
typedef __uint64_t uint64_t; void build_base_range(std::vector<uint32_t> &base_range);
void gen_range(std::vector<uint32_t> &release, int n1, int n2, int n3, int n4);
inline int binary_num(uint32_t binary, int length) { // get number of non-zero bit void find_all_case(std::vector<uint64_t> *all_case) {
int num = 0; all_case->clear();
for (int i = 0; i < length; ++i) { std::vector<uint32_t> base_range;
num += int((binary >> i) & 0x1); build_base_range(base_range);
} for (int head = 0; head < 16; ++head) { // address for 2x2 block
return num; if (head % 4 != 3) {
uint64_t prefix = int64_t(head) << 32;
for (auto range : base_range) { // combine 2x2 address and range
if (check_case(head, range)) {
binary_reverse(range);
all_case->emplace_back(prefix | range);
} }
inline void binary_reverse(uint32_t &range) { // reverse binary every 2 bits
range = ((range << 16) & 0xFFFF0000) | ((range >> 16) & 0x0000FFFF);
range = ((range << 8) & 0xFF00FF00) | ((range >> 8) & 0x00FF00FF);
range = ((range << 4) & 0xF0F0F0F0) | ((range >> 4) & 0x0F0F0F0F);
range = ((range << 2) & 0xCCCCCCCC) | ((range >> 2) & 0x33333333);
} }
inline void binary_to_str(uint64_t binary, char *string) {
for (int i = 0; i < 9; ++i, ++string) { // only read low 9 * 4 bits
*string = int8_t(binary >> (8 - i) * 4 & 0xF);
if (*string < 10) {
*string += 48; // 0 -> 48
} else {
*string += 55; // A -> 65
} }
} }
string[9] = 0x0; // string ending
} }
bool check_case(int head, uint32_t range) { // whether case is valid void build_base_range(std::vector<uint32_t> &base_range) {
uint32_t status = 0x33 << head; for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ (20 - 4 - 2) / 2
for (int addr = 0; range; range >>= 2) { for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 1x2 block
while (status >> addr & 0x1) { for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block
++addr; gen_range(base_range, (16 - n * 2 - n_1x1), (n - n_2x1), n_2x1, n_1x1);
}
switch (range & 0x3) {
case 0x0: // space
case 0x3: // 1x1
if (addr > 19) {
return false;
} }
status |= 0x1 << addr;
break;
case 0x1: // 1x2
if (addr % 4 == 3 || addr > 18 || status >> (addr + 1) & 0x1) {
return false;
} }
status |= 0x3 << addr;
break;
case 0x2: // 2x1
if (addr > 15 || status >> (addr + 4) & 0x1) {
return false;
} }
status |= 0x11 << addr; for (auto &bin : base_range) {
break; binary_reverse(bin);
} }
std::sort(base_range.begin(), base_range.end());
for (auto &bin : base_range) {
binary_reverse(bin);
} }
return true;
} }
void gen_range(std::vector<uint32_t> &release, int n1, int n2, int n3, int n4) { void gen_range(std::vector<uint32_t> &release, int n1, int n2, int n3, int n4) {
@ -114,51 +91,33 @@ void gen_range(std::vector<uint32_t> &release, int n1, int n2, int n3, int n4) {
} }
} }
void build_base_range(std::vector<uint32_t> &base_range) { bool check_case(int head, uint32_t range) { // whether case is valid
for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ (20 - 4 - 2) / 2 uint32_t status = 0x33 << head;
for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 1x2 block for (int addr = 0; range; range >>= 2) {
for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block while (status >> addr & 0x1) {
gen_range(base_range, (16 - n * 2 - n_1x1), (n - n_2x1), n_2x1, n_1x1); ++addr;
}
}
}
for (auto &bin : base_range) {
binary_reverse(bin);
}
std::sort(base_range.begin(), base_range.end());
for (auto &bin : base_range) {
binary_reverse(bin);
}
}
void find_all_case(std::vector<uint64_t> *all_case) {
all_case->clear();
std::vector<uint32_t> base_range;
build_base_range(base_range);
for (int head = 0; head < 16; ++head) { // address for 2x2 block
if (head % 4 != 3) {
uint64_t prefix = int64_t(head) << 32;
for (auto range : base_range) { // combine 2x2 address and range
if (check_case(head, range)) {
binary_reverse(range);
all_case->emplace_back(prefix | range);
} }
switch (range & 0x3) {
case 0x0: // space
case 0x3: // 1x1
if (addr > 19) {
return false;
} }
status |= 0x1 << addr;
break;
case 0x1: // 1x2
if (addr % 4 == 3 || addr > 18 || status >> (addr + 1) & 0x1) {
return false;
} }
status |= 0x3 << addr;
break;
case 0x2: // 2x1
if (addr > 15 || status >> (addr + 4) & 0x1) {
return false;
} }
status |= 0x11 << addr;
break;
} }
int main() {
std::vector<uint64_t> all_case;
find_all_case(&all_case);
// printf("count -> %lu\n", all_case.size());
for (auto code : all_case) {
char str[10];
binary_to_str(code, str);
printf("%s\n", str);
} }
return true;
return 0;
} }

9
case.h

@ -0,0 +1,9 @@
#ifndef _CASE_H_
#define _CASE_H_
#include <cstdint>
#include <vector>
void find_all_case(std::vector<uint64_t> *all_case);
#endif

31
common.cc

@ -0,0 +1,31 @@
#include "common.h"
//inline int binary_num(uint32_t binary, int length) { // get number of non-zero bit
int binary_num(uint32_t binary, int length) { // get number of non-zero bit
int num = 0;
for (int i = 0; i < length; ++i) {
num += int((binary >> i) & 0x1);
}
return num;
}
//inline void binary_reverse(uint32_t &range) { // reverse binary every 2 bits
void binary_reverse(uint32_t &range) { // reverse binary every 2 bits
range = ((range << 16) & 0xFFFF0000) | ((range >> 16) & 0x0000FFFF);
range = ((range << 8) & 0xFF00FF00) | ((range >> 8) & 0x00FF00FF);
range = ((range << 4) & 0xF0F0F0F0) | ((range >> 4) & 0x0F0F0F0F);
range = ((range << 2) & 0xCCCCCCCC) | ((range >> 2) & 0x33333333);
}
//inline void binary_to_str(uint64_t binary, char *string) {
void binary_to_str(uint64_t binary, char *string) {
for (int i = 0; i < 9; ++i, ++string) { // only read low 9 * 4 bits
*string = int8_t(binary >> (8 - i) * 4 & 0xF);
if (*string < 10) {
*string += 48; // 0 -> 48
} else {
*string += 55; // A -> 65
}
}
string[9] = 0x0; // string ending
}

10
common.h

@ -0,0 +1,10 @@
#ifndef _COMMON_H_
#define _COMMON_H_
#include <cstdint>
void binary_reverse(uint32_t &range);
int binary_num(uint32_t binary, int length);
void binary_to_str(uint64_t binary, char *string);
#endif

BIN
klotski

Binary file not shown.

55
klotski.cc

@ -0,0 +1,55 @@
#include "common.h"
#include "klotski.h"
uint64_t compact_code(uint64_t code) {
int block_num = 0;
uint64_t ret = 0;
uint32_t range = 0;
for (int addr = 0; code; ++addr, code >>= 3) {
switch (code & 0x7) {
case B_space:
range <<= 2;
break;
case B_1x2:
(range <<= 2) |= 0x1;
break;
case B_2x1:
(range <<= 2) |= 0x2;
break;
case B_1x1:
(range <<= 2) |= 0x3;
break;
case B_2x2:
ret |= uint64_t(addr) << 32;
default:
continue;
}
++block_num;
}
return ret | range << (16 - block_num) * 2;
}
uint64_t extract_code(uint64_t code) {
uint64_t ret = C_2x2 << (code >> 32) * 3;
auto range = uint32_t(code);
binary_reverse(range);
for (int addr = 0; range; range >>= 2) {
while (0x7 & ret >> addr) {
addr += 3;
}
switch (range & 0x3) {
case 0x1:
ret |= C_1x2 << addr;
break;
case 0x2:
ret |= C_2x1 << addr;
break;
case 0x3:
ret |= C_1x1 << addr;
break;
case 0x0:
addr += 3;
}
}
return ret;
}

73
klotski.h

@ -0,0 +1,73 @@
#ifndef _KLOTSKI_H_
#define _KLOTSKI_H_
#include <cstdint>
#define B_space 0x0
#define B_fill 0x7
#define B_1x2 0x1
#define B_2x1 0x2
#define B_1x1 0x3
#define B_2x2 0x4
#define C_1x1 int64_t(0x3)
#define C_1x2 int64_t(0x39)
#define C_2x1 int64_t(0x7002)
#define C_2x2 int64_t(0x3F03C)
#define F_1x1 int64_t(0x7)
#define F_1x2 int64_t(0x3F)
#define F_2x1 int64_t(0x7007)
#define F_2x2 int64_t(0x3F03F)
uint64_t compact_code(uint64_t code);
uint64_t extract_code(uint64_t code);
#endif
/*
uint64_t -> 0000 + [xxx] * 20
2x2 2x1 1x2 1x1
# # # # # #
# # #
00 01 02 03
04 05 06 07
08 09 10 11
12 13 14 15
16 17 18 19
x1 (%4) => 0 1 2 3
x3 (%4) => 0 3 2 1
*/
/*
======================================================
1x1 -> 011 000 000 000 -> 0000 0000 0011 -> 0x3
1x2 -> 001 111 000 000 -> 0000 0011 1001 -> 0x39
2x1 -> 010 000 000 000 -> 0000 0000 0010 -> 0x7002
111 000 000 000 -> 0000 0000 0111
2x2 -> 100 111 000 000 -> 0000 0011 1100 -> 0x3F03C
111 111 000 000 -> 0000 0011 1111
======================================================
1x1 -> 111 000 000 000 -> 0000 0000 0111 -> 0x7
1x2 -> 111 111 000 000 -> 0000 0011 1111 -> 0x3F
2x1 -> 111 000 000 000 -> 0000 0000 0111 -> 0x7007
111 000 000 000 -> 0000 0000 0111
2x2 -> 111 111 000 000 -> 0000 0011 1111 -> 0x3F03F
111 111 000 000 -> 0000 0011 1111
======================================================
*/

84
main.cc

@ -0,0 +1,84 @@
#include "case.h"
#include "klotski.h"
#include <cstdio>
#include <cstdint>
#include <vector>
void graph_output(uint64_t code) {
for (int i = 0; i < 20; ++i) {
switch (code & 0x7) {
case B_1x1:
printf("# ");
break;
case B_1x2:
printf("& ");
break;
case B_2x1:
printf("$ ");
break;
case B_2x2:
printf("@ ");
break;
case B_fill:
printf("* ");
break;
case B_space:
printf(". ");
break;
default:
printf("? ");
}
if ((i & 0x3) == 0x3) {
printf("\n");
}
code >>= 3;
}
}
int main() {
printf("Klotski engine\n");
// printf("%lx\n", compact_code(0x0E58FC85FFEBC4DB));
// printf("%lx\n", compact_code(0x0603EDF5CAFFF5E2));
// graph_output(extract_code(0x4FEA13400));
// printf("\n");
// graph_output(extract_code(0x1A9BF0C00));
// printf("\n");
std::vector<uint64_t> all_case;
find_all_case(&all_case);
printf("count -> %lu\n", all_case.size());
for (auto code : all_case) {
if (code != compact_code(extract_code(code))) {
printf("error -> %lx\n", code);
}
}
return 0;
// 0x4FEA13400
// # # # @ | 011 011 011 010 => 0100 1101 1011 -> 4DB
// * * & @ | 100 111 010 111 => 1110 1011 1100 -> EBC
// * * & $ | 111 111 111 010 => 0101 1111 1111 -> 5FF
// . + + $ | 000 001 111 111 => 1111 1100 1000 -> FC8
// . # ~ ~ | 000 011 001 111 => 1110 0101 1000 -> E58
// 0x0E58FC85FFEBC4DB
graph_output(0x0E58FC85FFEBC4DB);
printf("\n");
// 0x1A9BF0C00
// @ * * @ | 010 100 111 010 => 0101 1110 0010 -> 5E2
// @ * * @ | 111 111 111 111 => 1111 1111 1111 -> FFF
// $ ~ ~ $ | 010 001 111 010 => 0101 1100 1010 -> 5CA
// $ # # $ | 111 011 011 111 => 1110 1101 1111 -> EDF
// # . . # | 011 000 000 011 => 0110 0000 0011 -> 603
// 0x0603EDF5CAFFF5E2
graph_output(0x0603EDF5CAFFF5E2);
printf("\n");
return 0;
}

195
main.cpp

@ -1,195 +0,0 @@
#include <cstdio>
#include <cstdint>
#define B_space 0x0
#define B_fill 0x7
#define B_1x2 0x1
#define B_2x1 0x2
#define B_1x1 0x3
#define B_2x2 0x4
#define C_1x1 int64_t(0x3)
#define C_1x2 int64_t(0x39)
#define C_2x1 int64_t(0x7002)
#define C_2x2 int64_t(0x3F03C)
#define F_1x1 int64_t(0x7)
#define F_1x2 int64_t(0x3F)
#define F_2x1 int64_t(0x7007)
#define F_2x2 int64_t(0x3F03F)
/*
uint64_t -> 0000 + [xxx] * 20
2x2 2x1 1x2 1x1
# # # # # #
# # #
00 01 02 03
04 05 06 07
08 09 10 11
12 13 14 15
16 17 18 19
x1 (%4) => 0 1 2 3
x3 (%4) => 0 3 2 1
*/
/*
======================================================
1x1 -> 011 000 000 000 -> 0000 0000 0011 -> 0x3
1x2 -> 001 111 000 000 -> 0000 0011 1001 -> 0x39
2x1 -> 010 000 000 000 -> 0000 0000 0010 -> 0x7002
111 000 000 000 -> 0000 0000 0111
2x2 -> 100 111 000 000 -> 0000 0011 1100 -> 0x3F03C
111 111 000 000 -> 0000 0011 1111
======================================================
1x1 -> 111 000 000 000 -> 0000 0000 0111 -> 0x7
1x2 -> 111 111 000 000 -> 0000 0011 1111 -> 0x3F
2x1 -> 111 000 000 000 -> 0000 0000 0111 -> 0x7007
111 000 000 000 -> 0000 0000 0111
2x2 -> 111 111 000 000 -> 0000 0011 1111 -> 0x3F03F
111 111 000 000 -> 0000 0011 1111
======================================================
*/
void graph_output(uint64_t code) {
for (int i = 0; i < 20; ++i) {
switch (code & 0x7) {
case B_1x1:
printf("# ");
break;
case B_1x2:
printf("& ");
break;
case B_2x1:
printf("$ ");
break;
case B_2x2:
printf("@ ");
break;
case B_fill:
printf("* ");
break;
case B_space:
printf(". ");
break;
default:
printf("? ");
}
if ((i & 0x3) == 0x3) {
printf("\n");
}
code >>= 3;
}
}
uint64_t compact_code(uint64_t code) {
int block_num = 0;
uint64_t ret = 0;
uint32_t range = 0;
for (int addr = 0; code; ++addr, code >>= 3) {
switch (code & 0x7) {
case B_space:
range <<= 2;
break;
case B_1x2:
(range <<= 2) |= 0x1;
break;
case B_2x1:
(range <<= 2) |= 0x2;
break;
case B_1x1:
(range <<= 2) |= 0x3;
break;
case B_2x2:
ret |= uint64_t(addr) << 32;
default:
continue;
}
++block_num;
}
return ret | range << (16 - block_num) * 2;
}
inline void binary_reverse(uint32_t &range) { // reverse binary every 2 bits
range = ((range << 16) & 0xFFFF0000) | ((range >> 16) & 0x0000FFFF);
range = ((range << 8) & 0xFF00FF00) | ((range >> 8) & 0x00FF00FF);
range = ((range << 4) & 0xF0F0F0F0) | ((range >> 4) & 0x0F0F0F0F);
range = ((range << 2) & 0xCCCCCCCC) | ((range >> 2) & 0x33333333);
}
uint64_t extract_code(uint64_t code) {
uint64_t ret = C_2x2 << (code >> 32) * 3;
auto range = uint32_t(code);
binary_reverse(range);
for (int addr = 0; range; range >>= 2) {
while (0x7 & ret >> addr) {
addr += 3;
}
switch (range & 0x3) {
case 0x1:
ret |= C_1x2 << addr;
break;
case 0x2:
ret |= C_2x1 << addr;
break;
case 0x3:
ret |= C_1x1 << addr;
break;
case 0x0:
addr += 3;
}
}
return ret;
}
int main() {
printf("Klotski engine\n");
// printf("%lx\n", compact_code(0x0E58FC85FFEBC4DB));
// printf("%lx\n", compact_code(0x0603EDF5CAFFF5E2));
graph_output(extract_code(0x4FEA13400));
printf("\n");
graph_output(extract_code(0x1A9BF0C00));
printf("\n");
return 0;
// 0x4FEA13400
// # # # @ | 011 011 011 010 => 0100 1101 1011 -> 4DB
// * * & @ | 100 111 010 111 => 1110 1011 1100 -> EBC
// * * & $ | 111 111 111 010 => 0101 1111 1111 -> 5FF
// . + + $ | 000 001 111 111 => 1111 1100 1000 -> FC8
// . # ~ ~ | 000 011 001 111 => 1110 0101 1000 -> E58
// 0x0E58FC85FFEBC4DB
graph_output(0x0E58FC85FFEBC4DB);
printf("\n");
// 0x1A9BF0C00
// @ * * @ | 010 100 111 010 => 0101 1110 0010 -> 5E2
// @ * * @ | 111 111 111 111 => 1111 1111 1111 -> FFF
// $ ~ ~ $ | 010 001 111 010 => 0101 1100 1010 -> 5CA
// $ # # $ | 111 011 011 111 => 1110 1101 1111 -> EDF
// # . . # | 011 000 000 011 => 0110 0000 0011 -> 603
// 0x0603EDF5CAFFF5E2
graph_output(0x0603EDF5CAFFF5E2);
printf("\n");
return 0;
}
Loading…
Cancel
Save