Browse Source

feat: enable Analyse module

master
Dnomd343 2 years ago
parent
commit
37a620c503
  1. 4
      src/CMakeLists.txt
  2. 258
      src/analyse/analyse.cc
  3. 32
      src/analyse/analyse.h
  4. 184
      src/analyse/backtrack.cc
  5. 2
      src/fast_cal/fast_cal.h
  6. 68
      src/main.cc

4
src/CMakeLists.txt

@ -23,7 +23,7 @@ add_subdirectory(short_code)
add_subdirectory(common_code) add_subdirectory(common_code)
add_subdirectory(core) add_subdirectory(core)
#add_subdirectory(analyse) add_subdirectory(analyse)
add_subdirectory(fast_cal) add_subdirectory(fast_cal)
################################################ ################################################
@ -40,7 +40,7 @@ target_link_libraries(klotski short_code)
target_link_libraries(klotski common_code) target_link_libraries(klotski common_code)
target_link_libraries(klotski core) target_link_libraries(klotski core)
#target_link_libraries(klotski analyse) target_link_libraries(klotski analyse)
target_link_libraries(klotski fast_cal) target_link_libraries(klotski fast_cal)
target_link_libraries(klotski pthread) target_link_libraries(klotski pthread)

258
src/analyse/analyse.cc

@ -7,7 +7,7 @@
#include "raw_code.h" #include "raw_code.h"
#include "common.h" #include "common.h"
Core Analyse::new_core() { Core Analyse::init() {
return Core( return Core(
[this](auto &&code, auto &&mask) { // lambda as function pointer [this](auto &&code, auto &&mask) { // lambda as function pointer
new_case(std::forward<decltype(code)>(code), std::forward<decltype(mask)>(mask)); new_case(std::forward<decltype(code)>(code), std::forward<decltype(mask)>(mask));
@ -15,260 +15,54 @@ Core Analyse::new_core() {
); );
} }
void dump_python_case(uint64_t raw_code) {
std::string result;
for (int addr = 0; raw_code; ++addr, raw_code >>= 3) {
uint32_t x = addr % 4;
uint32_t y = (addr - x) / 4;
char block[11]; // eg: `[0,0,1,1]`
switch (raw_code & 0b111) { void Analyse::build(uint64_t code) {
case B_1x1:
sprintf(block, "[%d,%d,1,1],", x, y);
result += block;
break;
case B_1x2:
sprintf(block, "[%d,%d,1,2],", x, y);
result += block;
break;
case B_2x1:
sprintf(block, "[%d,%d,2,1],", x, y);
result += block;
break;
case B_2x2:
sprintf(block, "[%d,%d,2,2],", x, y);
result += block;
break;
default:
continue;
}
}
result[result.length() - 1] = '\0'; // remove last `,`
std::cout << '[' << result.c_str() << ']';
}
void Analyse::backtrack(const std::vector<uint64_t> &raw_code_list) {
// backtrack start at code
// std::cout << "start backtrack" << std::endl;
std::queue<analyse_t*> track_cache;
std::vector<std::vector<backtrack_t*> > layer_data;
std::unordered_map<uint64_t, backtrack_t> track_data;
// TODO: confirm that code exist
/// layer init
// auto max_step = cases[code].step; // TODO: update max step cal
// auto max_step = 81;
uint32_t max_step = 0;
for (const auto &code : raw_code_list) {
// TODO: check whether cases include code
if (cases[code].step > max_step) {
max_step = cases[code].step;
}
}
layer_data.resize(max_step + 1);
/// init track begin cases
// {
// auto layer_num = cases[code].step;
//
// track_cache.emplace(&cases[code]);
//
// auto ptr = track_data.emplace(code, backtrack_t {
// .code = code,
// .layer_num = layer_num,
// .layer_index = (uint32_t)layer_data[layer_num].size(),
// });
//
// layer_data[layer_num].emplace_back(&ptr.first->second);
// }
for (auto code : raw_code_list) {
auto layer_num = cases[code].step;
track_cache.emplace(&cases[code]);
auto ptr = track_data.emplace(code, backtrack_t { auto core = init();
.code = code,
.layer_num = layer_num,
.layer_index = (uint32_t)layer_data[layer_num].size(),
});
layer_data[layer_num].emplace_back(&ptr.first->second);
}
// for (const auto &t : track_data) {
// std::cout << RawCode(t.second.code).dump_case() << std::endl;
// std::cout << t.second.layer_num << " " << t.second.layer_index << std::endl;
// }
while (!track_cache.front()->src.empty()) {
auto current = track_cache.front();
for (auto src : current->src) {
auto find_ret = track_data.find(src->code);
if (find_ret != track_data.end()) { // already exist
find_ret->second.next.emplace_back(
&track_data[current->code]
);
} else { // insert new case
track_cache.emplace(src);
auto ptr = track_data.emplace(src->code, backtrack_t {
.code = src->code,
.layer_num = src->step,
.layer_index = (uint32_t)layer_data[src->step].size(),
.next = std::list<backtrack_t*>{&track_data[current->code]},
});
layer_data[src->step].emplace_back(&ptr.first->second);
}
}
track_cache.pop();
} cases.clear();
cases.reserve(65536);
backtrack_t *root = &track_data[track_cache.front()->code];
// std::cout << "Size = " << track_data.size() << std::endl;
// std::cout << "Root" << std::endl;
// std::cout << RawCode(root->code).dump_case() << std::endl;
// for (auto layer : layer_data) {
// std::cout << "-----------------------" << std::endl;
// std::cout << "layer size = " << layer.size() << std::endl;
//
// for (auto element : layer) {
// std::cout << "(" << element->layer_num << ", " << element->layer_index << ") -> ";
// for (auto next : element->next) {
// std::cout << "(" << next->layer_num << ", " << next->layer_index << ") ";
// }
// std::cout << std::endl;
//
// std::cout << RawCode(element->code).dump_case() << std::endl;
// }
// }
printf("layer:\n");
for (uint32_t num = 0; num < layer_data.size(); ++num) {
auto layer = &layer_data[num];
printf("- [");
for (auto element : *layer) {
// printf(&",\"%015lX\""[element == (*layer)[0]], element->code);
printf("%s", &","[element == (*layer)[0]]);
dump_python_case(element->code);
}
printf("] # layer %d\n", num);
}
printf("\n");
printf("next:\n");
for (uint32_t num = 0; num + 1 < layer_data.size(); ++num) {
auto layer = &layer_data[num];
printf("- ");
for (uint32_t index = 0; index < layer->size(); ++index) {
auto element = &(*layer)[index];
printf("%s", &" - ["[!index * 2]);
bool first_flag = true;
for (auto next : (*element)->next) {
printf(&",%d"[first_flag], next->layer_index);
if (first_flag) { first_flag = false; }
}
printf("] # (%d, %d) -> %d\n", num, index, num + 1);
}
}
}
void Analyse::start_analyse(uint64_t code) {
auto core = new_core();
cases.empty(); std::queue<analyse_t*>{}.swap(cache);
cache.empty();
cases.reserve(65536);
cache.emplace(&cases.emplace(code, analyse_t { cache.emplace(&cases.emplace(code, analyse_t {
.code = code, .code = code,
.mask = 0, .mask = 0,
.step = 0, .step = 0,
// .highlight = false, .src = std::list<analyse_t*>{},
// .src = std::move(std::list<analyse_t*>{}), // .src = std::vector<analyse_t*>{},
// .src = std::set<analyse_t*>{},
// .src = std::unordered_set<analyse_t*>{},
}).first->second); }).first->second);
while (!cache.empty()) { while (!cache.empty()) {
core.next_cases(cache.front()->code, cache.front()->mask);
core.next_step(cache.front()->code, cache.front()->mask);
cache.pop(); cache.pop();
} }
// std::cout << "size: " << cases.size() << std::endl; std::cout << "size: " << cases.size() << std::endl;
} }
void Analyse::new_case(uint64_t code, uint64_t mask) { void Analyse::new_case(uint64_t code, uint64_t mask) {
// auto temp = cases.emplace(code, analyse_t {
// .code = code,
// .mask = mask,
// .step = cache.front()->step + 1,
// .src = std::move(std::list<analyse_t*>{cache.front()})
// });
//
// if (temp.second) {
// cache.emplace(&temp.first->second);
// } else {
// temp.first->second.mask |= mask;
//
// if (temp.first->second.step != cache.front()->step) {
// temp.first->second.src.push_back(cache.front());
// }
//
// }
auto current = cases.find(code); auto current = cases.find(code);
if (current != cases.end()) { // find existed case if (current != cases.end()) { // new case already exist
if (current->second.step == cache.front()->step + 1) { // new case at next layer
if (current->second.step == cache.front()->step + 1) {
current->second.mask |= mask; // update mask info current->second.mask |= mask; // update mask info
current->second.src.emplace_back(cache.front()); // link more parent case
if (current->second.step != cache.front()->step) { // current->second.src.emplace(cache.front()); // link more parent case
current->second.src.push_back(cache.front());
}
} }
} else { // new case not exist
return; cache.emplace(&cases.emplace(code, analyse_t { // record new case
.code = code,
.mask = mask,
.step = cache.front()->step + 1,
.src = std::list<analyse_t*>{cache.front()}, // link parent case
// .src = std::vector<analyse_t*>{cache.front()}, // link parent case
// .src = std::set<analyse_t*>{cache.front()}, // link parent case
// .src = std::unordered_set<analyse_t*>{cache.front()}, // link parent case
}).first->second);
} }
cache.emplace(&cases.emplace(code, analyse_t {
.code = code,
.mask = mask,
.step = cache.front()->step + 1,
// .highlight = false,
.src = std::move(std::list<analyse_t*>{cache.front()}),
}).first->second);
} }

32
src/analyse/analyse.h

@ -4,45 +4,43 @@
#include <cstdint> #include <cstdint>
#include <unordered_map> #include <unordered_map>
//#include <set>
#include <list> #include <list>
//#include <unordered_set> #include <set>
#include <unordered_set>
class Analyse { class Analyse {
public: public:
struct analyse_t { struct analyse_t {
uint64_t code; uint64_t code;
uint64_t mask; uint64_t mask;
uint32_t step; uint32_t step;
// bool highlight;
// std::vector<analyse_t*> src;
std::list<analyse_t*> src; std::list<analyse_t*> src;
// std::vector<analyse_t*> src;
// std::set<analyse_t*> src; // std::set<analyse_t*> src;
// std::unordered_set<analyse_t*> src; // std::unordered_set<analyse_t*> src;
}; };
struct backtrack_t { // struct backtrack_t {
uint64_t code; // uint64_t code;
// uint32_t layer_num;
uint32_t layer_num; // uint32_t layer_index;
uint32_t layer_index; // std::list<backtrack_t*> next;
// };
std::list<backtrack_t*> next;
};
std::queue<analyse_t*> cache; std::queue<analyse_t*> cache;
std::unordered_map<uint64_t, analyse_t> cases; std::unordered_map<uint64_t, analyse_t> cases;
inline Core new_core(); // inline Core new_core();
// TODO: backtrack for multi-codes // TODO: backtrack for multi-codes
// void backtrack(uint64_t code); // void backtrack(uint64_t code);
void backtrack(const std::vector<uint64_t> &raw_code_list); // void backtrack(const std::vector<uint64_t> &raw_code_list);
void build(uint64_t code);
void start_analyse(uint64_t code); // inline Core init(uint64_t code);
inline Core init();
void new_case(uint64_t code, uint64_t mask); void new_case(uint64_t code, uint64_t mask);

184
src/analyse/backtrack.cc

@ -0,0 +1,184 @@
void dump_python_case(uint64_t raw_code) {
std::string result;
for (int addr = 0; raw_code; ++addr, raw_code >>= 3) {
uint32_t x = addr % 4;
uint32_t y = (addr - x) / 4;
char block[11]; // eg: `[0,0,1,1]`
switch (raw_code & 0b111) {
case B_1x1:
sprintf(block, "[%d,%d,1,1],", x, y);
result += block;
break;
case B_1x2:
sprintf(block, "[%d,%d,1,2],", x, y);
result += block;
break;
case B_2x1:
sprintf(block, "[%d,%d,2,1],", x, y);
result += block;
break;
case B_2x2:
sprintf(block, "[%d,%d,2,2],", x, y);
result += block;
break;
default:
continue;
}
}
result[result.length() - 1] = '\0'; // remove last `,`
std::cout << '[' << result.c_str() << ']';
}
void Analyse::backtrack(const std::vector<uint64_t> &raw_code_list) {
// backtrack start at code
// std::cout << "start backtrack" << std::endl;
std::queue<analyse_t*> track_cache;
std::vector<std::vector<backtrack_t*> > layer_data;
std::unordered_map<uint64_t, backtrack_t> track_data;
// TODO: confirm that code exist
/// layer init
// auto max_step = cases[code].step; // TODO: update max step cal
// auto max_step = 81;
uint32_t max_step = 0;
for (const auto &code : raw_code_list) {
// TODO: check whether cases include code
if (cases[code].step > max_step) {
max_step = cases[code].step;
}
}
layer_data.resize(max_step + 1);
/// init track begin cases
// {
// auto layer_num = cases[code].step;
//
// track_cache.emplace(&cases[code]);
//
// auto ptr = track_data.emplace(code, backtrack_t {
// .code = code,
// .layer_num = layer_num,
// .layer_index = (uint32_t)layer_data[layer_num].size(),
// });
//
// layer_data[layer_num].emplace_back(&ptr.first->second);
// }
for (auto code : raw_code_list) {
auto layer_num = cases[code].step;
track_cache.emplace(&cases[code]);
auto ptr = track_data.emplace(code, backtrack_t {
.code = code,
.layer_num = layer_num,
.layer_index = (uint32_t)layer_data[layer_num].size(),
});
layer_data[layer_num].emplace_back(&ptr.first->second);
}
// for (const auto &t : track_data) {
// std::cout << RawCode(t.second.code).dump_case() << std::endl;
// std::cout << t.second.layer_num << " " << t.second.layer_index << std::endl;
// }
while (!track_cache.front()->src.empty()) {
auto current = track_cache.front();
for (auto src : current->src) {
auto find_ret = track_data.find(src->code);
if (find_ret != track_data.end()) { // already exist
find_ret->second.next.emplace_back(
&track_data[current->code]
);
} else { // insert new case
track_cache.emplace(src);
auto ptr = track_data.emplace(src->code, backtrack_t {
.code = src->code,
.layer_num = src->step,
.layer_index = (uint32_t)layer_data[src->step].size(),
.next = std::list<backtrack_t*>{&track_data[current->code]},
});
layer_data[src->step].emplace_back(&ptr.first->second);
}
}
track_cache.pop();
}
backtrack_t *root = &track_data[track_cache.front()->code];
// std::cout << "Size = " << track_data.size() << std::endl;
// std::cout << "Root" << std::endl;
// std::cout << RawCode(root->code).dump_case() << std::endl;
// for (auto layer : layer_data) {
// std::cout << "-----------------------" << std::endl;
// std::cout << "layer size = " << layer.size() << std::endl;
//
// for (auto element : layer) {
// std::cout << "(" << element->layer_num << ", " << element->layer_index << ") -> ";
// for (auto next : element->next) {
// std::cout << "(" << next->layer_num << ", " << next->layer_index << ") ";
// }
// std::cout << std::endl;
//
// std::cout << RawCode(element->code).dump_case() << std::endl;
// }
// }
printf("layer:\n");
for (uint32_t num = 0; num < layer_data.size(); ++num) {
auto layer = &layer_data[num];
printf("- [");
for (auto element : *layer) {
// printf(&",\"%015lX\""[element == (*layer)[0]], element->code);
printf("%s", &","[element == (*layer)[0]]);
dump_python_case(element->code);
}
printf("] # layer %d\n", num);
}
printf("\n");
printf("next:\n");
for (uint32_t num = 0; num + 1 < layer_data.size(); ++num) {
auto layer = &layer_data[num];
printf("- ");
for (uint32_t index = 0; index < layer->size(); ++index) {
auto element = &(*layer)[index];
printf("%s", &" - ["[!index * 2]);
bool first_flag = true;
for (auto next : (*element)->next) {
printf(&",%d"[first_flag], next->layer_index);
if (first_flag) { first_flag = false; }
}
printf("] # (%d, %d) -> %d\n", num, index, num + 1);
}
}
}

2
src/fast_cal/fast_cal.h

@ -44,6 +44,6 @@ private:
std::queue<fast_cal_t*> cache; std::queue<fast_cal_t*> cache;
std::unordered_map<uint64_t, fast_cal_t> cases; std::unordered_map<uint64_t, fast_cal_t> cases;
Core init(uint64_t code); inline Core init(uint64_t code);
void new_case(uint64_t code, uint64_t mask); void new_case(uint64_t code, uint64_t mask);
}; };

68
src/main.cc

@ -15,46 +15,52 @@
int main() { int main() {
// BasicRanges::build(); BasicRanges::build();
std::vector<RawCode> test_cases; // std::vector<RawCode> test_cases;
{ // {
AllCases::build(); // AllCases::build();
std::vector<uint64_t> all_cases; // std::vector<uint64_t> all_cases;
for (uint64_t head = 0; head < 16; ++head) { // for (uint64_t head = 0; head < 16; ++head) {
for (const auto &range : AllCases::fetch()[head]) { // for (const auto &range : AllCases::fetch()[head]) {
all_cases.emplace_back(head << 32 | range); // all_cases.emplace_back(head << 32 | range);
} // }
} // }
for (uint32_t i = 0; i < 10000; ++i) { // for (uint32_t i = 0; i < 1000; ++i) {
test_cases.emplace_back( // test_cases.emplace_back(
RawCode::from_common_code(all_cases.at(i * 2933)) // RawCode::from_common_code(all_cases.at(i * 29334))
); // );
} // }
} // }
std::cout << "test size -> " << test_cases.size() << std::endl; // std::cout << "test size -> " << test_cases.size() << std::endl;
// std::cout << "wait 3s" << std::endl; // std::cout << "wait 3s" << std::endl;
// sleep(3); // sleep(3);
std::cout << "start benchmark" << std::endl; // std::cout << "start benchmark" << std::endl;
auto start_time = clock(); auto start_time = clock();
// AllCases::build(); // AllCases::build();
{ // {
auto fc = FastCal(); // auto fc = FastCal();
for (uint32_t i = 0; i < test_cases.size(); ++i) { // for (uint32_t i = 0; i < test_cases.size(); ++i) {
fc.solve(test_cases[i]); // fc.solve(test_cases[i]);
if (i % 1000 == 0) { // if (i % 1000 == 0) {
std::cout << (i * 100 / test_cases.size()) << "%" << std::endl; // std::cout << (i * 100 / test_cases.size()) << "%" << std::endl;
} // }
} // }
} // for (auto code : test_cases) {
// fc.solve(code);
// }
// }
auto a = Analyse();
a.build((uint64_t)RawCode::from_common_code("1a9bf0c"));
// auto raw_code = CommonCode("A5D3AF0").to_raw_code().unwrap(); // auto raw_code = CommonCode("A5D3AF0").to_raw_code().unwrap();
// auto a = Analyse(); // auto a = Analyse();
@ -92,11 +98,11 @@ int main() {
// std::cout << CommonCode::from_short_code("AXCZN") << std::endl; // std::cout << CommonCode::from_short_code("AXCZN") << std::endl;
std::cerr << (clock() - start_time) / CLOCKS_PER_SEC << "s" << std::endl; // std::cerr << (clock() - start_time) / CLOCKS_PER_SEC << "s" << std::endl;
// std::cerr << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; // std::cerr << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl;
// std::cerr << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl; std::cerr << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl;
std::cout << "complete benchmark" << std::endl; // std::cout << "complete benchmark" << std::endl;
// pause(); // pause();

Loading…
Cancel
Save