From b683ae7687e8cdb307625c3eeef68820d7ac9749 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 27 Oct 2024 11:24:48 +0800 Subject: [PATCH] feat: export all layer cases --- src/core/CMakeLists.txt | 2 - src/core/fast_cal/fast_cal.h | 83 +++------------- src/core/fast_cal/internal/cal_core.cc | 105 --------------------- src/core/fast_cal/internal/demo.cc | 55 ++--------- src/core/fast_cal/internal/fast_cal.cc | 95 ------------------- src/core/fast_cal/internal/fast_cal.inl | 8 +- src/core/fast_cal/internal/layer_queue.inl | 69 +++++++++++--- src/core/fast_cal/layer_queue.h | 44 ++++++--- src/core/main.cc | 17 +++- 9 files changed, 126 insertions(+), 352 deletions(-) delete mode 100644 src/core/fast_cal/internal/cal_core.cc delete mode 100644 src/core/fast_cal/internal/fast_cal.cc diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 61ef420..65883b6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -20,8 +20,6 @@ set(KLOTSKI_CORE_SRC mover/internal/mover.cc - fast_cal/internal/cal_core.cc - fast_cal/internal/fast_cal.cc fast_cal/internal/demo.cc group/internal/group_union.cc diff --git a/src/core/fast_cal/fast_cal.h b/src/core/fast_cal/fast_cal.h index fe12912..d392d27 100644 --- a/src/core/fast_cal/fast_cal.h +++ b/src/core/fast_cal/fast_cal.h @@ -4,78 +4,17 @@ #pragma once -// #include #include #include #include -// #include +#include "group/group.h" #include "mover/mover.h" +#include "layer_queue.h" #include "raw_code/raw_code.h" -#include "group/group.h" - -// #include - -#include - #include -// using klotski::codec::RawCode; -// using klotski::mover::MaskMover; - -// TODO: using prime number -// const uint32_t FC_MAP_RESERVE = 65536 * 8; - -/// FastCal not found -> return invalid raw code -// const RawCode FC_NOT_FOUND = RawCode::unsafe_create(0); - -// class FastCal { -// public: -// typedef std::function match_t; - - /// setting root code - // void set_root(const RawCode &code); - // explicit FastCal(const RawCode &code); - - /// backtrack functions - // int step_num(const RawCode &code); - // std::vector backtrack(const RawCode &code); - - /// BFS search functions - // void build(); - // RawCode solve(); - // std::vector furthest(); - // std::vector solve_multi(); - // RawCode target(const match_t &match); - // std::vector target_multi(const match_t &match); - - // RawCode demo(); - - /// static BFS search functions - // static std::vector resolve(const RawCode &start); - // static std::vector> to_furthest(const RawCode &start); - // static std::vector> resolve_multi(const RawCode &start); - // static std::vector search(const RawCode &start, const match_t &match); - // static std::vector> search_multi(const RawCode &start, const match_t &match); - -// private: - // struct fast_cal_t { - // uint64_t code; - // uint64_t mask; - // fast_cal_t *last; - // }; - - // uint64_t root; - // std::queue cache; - // std::unordered_map cases; - - // inline MaskMover init(uint64_t code); - // void new_case(uint64_t code, uint64_t mask); -// }; - -#include "layer_queue.h" - namespace klotski::fast_cal { class FastCalPro { @@ -88,13 +27,13 @@ public: // TODO: add global build - /// Calculate the case with minimum steps. + /// Calculate a minimum-step case. std::optional solve(); - /// Calculate the cases with maximum steps. + /// Calculate all the maximum-step cases. std::vector furthest(); - /// Calculate all of the minimum-step cases. + /// Calculate all the minimum-step cases. std::vector solve_multi(); /// Calculate the first case that meets the requirement. @@ -102,10 +41,11 @@ public: // ------------------------------------------------------------------------------------- // - /// Backtrack the shortest path from specified case. - std::vector backtrack(codec::RawCode code) const; + /// Export all group cases with different minimum-step. + [[nodiscard]] std::vector> exports() const; - // std::vector> export_layers() const; + /// Backtrack one of the minimum-step path from specified case. + [[nodiscard]] std::vector backtrack(codec::RawCode code) const; // ------------------------------------------------------------------------------------- // @@ -125,7 +65,8 @@ private: uint64_t back; }; - LayerQueue codes_; + // codec::RawCode root_; + LayerQueue codes_; phmap::flat_hash_map cases_; // ------------------------------------------------------------------------------------- // @@ -133,6 +74,4 @@ private: } // namespace klotski::fast_cal -// klotski::codec::RawCode FastCal_demo(klotski::codec::RawCode code); - #include "internal/fast_cal.inl" diff --git a/src/core/fast_cal/internal/cal_core.cc b/src/core/fast_cal/internal/cal_core.cc deleted file mode 100644 index 04b511a..0000000 --- a/src/core/fast_cal/internal/cal_core.cc +++ /dev/null @@ -1,105 +0,0 @@ -#include "fast_cal/fast_cal.h" - -// MaskMover FastCal::init(uint64_t code) { // initialize process -// /// reset working data -// cases.clear(); -// cases.reserve(FC_MAP_RESERVE); // hashmap pre-reserve -// std::queue{}.swap(cache); -// -// /// insert root node -// cache.emplace(&cases.emplace(code, fast_cal_t { -// .code = code, -// .mask = 0, -// .last = nullptr, // without parent node -// }).first->second); -// -// /// import klotski mover -// return MaskMover( -// [this](auto &&code, auto &&mask) { // lambda as function pointer -// new_case(std::forward(code), std::forward(mask)); -// } -// ); -// } - -/// callback function for new case -// void FastCal::new_case(uint64_t code, uint64_t mask) { -// auto current = cases.find(code); -// if (current != cases.end()) { // find existed case -// current->second.mask |= mask; // update mask info -// return; -// } -// cache.emplace(&cases.emplace(code, fast_cal_t { // record new case -// .code = code, -// .mask = mask, -// .last = cache.front(), // link parent case -// }).first->second); -// } - -/// build total search tree -// void FastCal::build() { -// auto core = init(root); -// while (!cache.empty()) { -// core.next_cases(cache.front()->code, cache.front()->mask); -// cache.pop(); -// } -// } - -/// found first matched target -// RawCode FastCal::target(const match_t &match) { -// auto core = init(root); -// while (!cache.empty()) { -// if (match(cache.front()->code)) { -// return RawCode::unsafe_create(cache.front()->code); // match target -// } -// core.next_cases(cache.front()->code, cache.front()->mask); -// cache.pop(); -// } -// return FC_NOT_FOUND; // target not found -// } - -/// found all of the furthest cases -// std::vector FastCal::furthest() { -// auto core = init(root); -// auto layer_end = cache.back(); -// std::vector layer_cases; -// /// start BFS search -// while (!cache.empty()) { -// core.next_cases(cache.front()->code, cache.front()->mask); -// layer_cases.emplace_back( -// RawCode::unsafe_create(cache.front()->code) // record layer cases -// ); -// if (cache.front() == layer_end) { // reach layer ending -// if (cache.size() == 1) { -// break; // stop loop at last layer -// } -// layer_cases.clear(); -// layer_end = cache.back(); // reset layer ending -// } -// cache.pop(); -// } -// return layer_cases; // release the latest layer cases -// } - -/// found multi-targets matched in first same layer -// std::vector FastCal::target_multi(const match_t &match) { -// auto core = init(root); -// auto layer_end = cache.back(); -// std::vector matched; // matched list -// /// start BFS search -// while (!cache.empty()) { -// if (match(cache.front()->code)) { // match target -// matched.emplace_back( -// RawCode::unsafe_create(cache.front()->code) // record matched cases -// ); -// } -// core.next_cases(cache.front()->code, cache.front()->mask); -// if (cache.front() == layer_end) { // reach layer ending -// if (!matched.empty()) { -// return matched; // stop at first matched layer -// } -// layer_end = cache.back(); // reset layer ending -// } -// cache.pop(); -// } -// return std::vector{}; // no target found -// } diff --git a/src/core/fast_cal/internal/demo.cc b/src/core/fast_cal/internal/demo.cc index a14ab37..c78a16c 100644 --- a/src/core/fast_cal/internal/demo.cc +++ b/src/core/fast_cal/internal/demo.cc @@ -2,8 +2,6 @@ #include -//#include - #include #include "mover/mover.h" @@ -23,7 +21,9 @@ static KLSK_INLINE bool is_solved(uint64_t raw_code) { } std::optional FastCalPro::solve() { - // TODO: check root case + // if (is_solved(root_.unwrap())) { + // return root_; + // } uint64_t solution = 0; auto mover = MaskMover([this, &solution](uint64_t code, uint64_t mask) { @@ -89,9 +89,7 @@ std::vector FastCalPro::furthest() { while (true) { spawn_next(mover); if (codes_.is_ending()) { - return codes_.layer_cases() | std::views::transform([](uint64_t code) { - return RawCode::unsafe_create(code); - }) | std::ranges::to(); + return codes_.last_layer(); } } } @@ -109,45 +107,6 @@ std::vector FastCalPro::backtrack(RawCode code) const { return path; } -// std::vector> FastCalPro::export_layers() const { - // auto layer = furthest(); - // - // std::vector> result; - // result.emplace_back(layer); - // - // for (auto code : layer) { - // std::cout << code << std::endl; - // } - - // return {}; -// } - -// RawCode FastCal_demo(RawCode raw_code) { -// FastCalPro fc {raw_code}; -// return fc.solve().value(); - - // auto tmp = fc.solve(); - // std::cout << tmp.value().to_common_code() << std::endl; - - // auto path = fc.backtrack(tmp.value()); - // std::cout << path.size() << std::endl; - - // fc.export_layers(); - -// auto tmp = fc.solve_multi(); -// for (const auto x : tmp) { -// std::cout << x.to_common_code() << std::endl; -// } - -// auto tmp = fc.furthest(); -// for (const auto x : tmp) { -// std::cout << x.to_common_code() << std::endl; -// } - -// auto tmp = fc.achieve([](RawCode r) { -// return r == 0x7F87E0E5BFFF492; -// }); -// std::cout << tmp.value().to_common_code() << std::endl; - - // return RawCode::unsafe_create(0); -// } +std::vector> FastCalPro::exports() const { + return codes_.all_layers(); +} diff --git a/src/core/fast_cal/internal/fast_cal.cc b/src/core/fast_cal/internal/fast_cal.cc deleted file mode 100644 index 3ef2fbe..0000000 --- a/src/core/fast_cal/internal/fast_cal.cc +++ /dev/null @@ -1,95 +0,0 @@ -#include - -#include - -#include "utils/common.h" -#include "fast_cal/fast_cal.h" -#include "raw_code/raw_code.h" - -#include "group/group.h" - -// FastCal::FastCal(const RawCode &code) { -// this->root = (uint64_t)code; -// } - -// void FastCal::set_root(const RawCode &code) { -// this->root = (uint64_t)code; -// } - -/// klotski resolved -> 2x2 block at address 13 (aka 0xD) -// auto resolved = [](uint64_t code) { -// return ((code >> (3 * 0xD)) & 0b111) == BLOCK_2x2; // check 2x2 block address -// }; - -// RawCode FastCal::solve() { -// return FastCal::target(resolved); -// } - -// std::vector FastCal::solve_multi() { -// return FastCal::target_multi(resolved); -// } - -// std::vector FastCal::resolve(const RawCode &start) { -// return FastCal::search(start, resolved); -// } - -// std::vector> FastCal::resolve_multi(const RawCode &start) { -// return FastCal::search_multi(start, resolved); -// } - -/// backtrack of FastCal tree -// int FastCal::step_num(const RawCode &code) { -// auto tmp = cases.find((uint64_t)code); -// if (tmp == cases.end()) { -// return -1; // code not exist -// } -// int num = 0; // step number -// auto node = &tmp->second; // backtrack entry -// while ((node = node->last) != nullptr) { -// ++num; -// } -// return num; -// } - -// std::vector FastCal::backtrack(const RawCode &code) { -// auto tmp = cases.find((uint64_t)code); -// if (tmp == cases.end()) { -// return std::vector{}; // code not exist -// } -// auto node = &tmp->second; // backtrack entry -// std::vector path; // backtrack path -// while (node != nullptr) { -// path.emplace_back(RawCode::unsafe_create(node->code)); // record path info -// node = node->last; -// } -// std::reverse(path.begin(), path.end()); // reverse path cases -// return path; -// } - -/// static BFS search functions -// std::vector> FastCal::to_furthest(const RawCode &start) { -// auto fc = FastCal(start); -// std::vector> result; -// for (const auto &furthest : fc.furthest()) { -// result.emplace_back(fc.backtrack(furthest)); // backtrack every furthest cases -// } -// return result; -// } - -// std::vector FastCal::search(const RawCode &start, const match_t &match) { -// auto fc = FastCal(start); -// auto result = fc.target(match); -// if (result == FC_NOT_FOUND) { -// return std::vector{}; // target not matched -// } -// return fc.backtrack(result); // backtrack target path -// } - -// std::vector> FastCal::search_multi(const RawCode &start, const match_t &match) { -// auto fc = FastCal(start); -// std::vector> result; -// for (const auto &target : fc.target_multi(match)) { -// result.emplace_back(fc.backtrack(target)); // backtrack every target -// } -// return result; -// } diff --git a/src/core/fast_cal/internal/fast_cal.inl b/src/core/fast_cal/internal/fast_cal.inl index f2da011..eb99a9d 100644 --- a/src/core/fast_cal/internal/fast_cal.inl +++ b/src/core/fast_cal/internal/fast_cal.inl @@ -2,7 +2,7 @@ namespace klotski::fast_cal { -inline FastCalPro::FastCalPro(codec::RawCode raw_code) : codes_(cases::GroupUnion::from_raw_code(raw_code).max_group_size(), {raw_code.unwrap()}) { +inline FastCalPro::FastCalPro(codec::RawCode raw_code) : codes_({raw_code}, cases::GroupUnion::from_raw_code(raw_code).max_group_size()) { auto reserve = cases::GroupUnion::from_raw_code(raw_code).max_group_size(); // cases_.reserve(static_cast(25955 * 1.56)); cases_.reserve(static_cast(reserve * 1.56)); @@ -16,15 +16,15 @@ inline KLSK_INLINE bool FastCalPro::try_emplace(uint64_t code, uint64_t mask) { } cases_.emplace(code, data_t { .mask = mask, - .back = codes_.current(), + .back = codes_.current().unwrap(), }); - codes_.emplace(code); + codes_.emplace(codec::RawCode::unsafe_create(code)); return true; } inline KLSK_INLINE void FastCalPro::spawn_next(mover::MaskMover &mover) { auto curr = codes_.current(); - mover.next_cases(curr, cases_.find(curr)->second.mask); + mover.next_cases(curr.unwrap(), cases_.find(curr.unwrap())->second.mask); codes_.next(); } diff --git a/src/core/fast_cal/internal/layer_queue.inl b/src/core/fast_cal/internal/layer_queue.inl index c6e47d1..588fd2a 100644 --- a/src/core/fast_cal/internal/layer_queue.inl +++ b/src/core/fast_cal/internal/layer_queue.inl @@ -3,19 +3,38 @@ namespace klotski { template -inline LayerQueue::LayerQueue(size_t reserve, std::initializer_list first_layer) { - data_.resize(reserve); +LayerQueue::LayerQueue(std::initializer_list first_layer, const size_t reserve) { + // data_.resize(reserve); + + static_assert(std::is_trivial_v); + + // data_ = new T[reserve]; + data_ = (T*)std::malloc(sizeof(T) * reserve); + + queue_begin_ = 0; + queue_end_ = 0; for (auto x : first_layer) { emplace(x); } + + layer_begin_ = 0; layer_end_ = first_layer.size(); + layers_.reserve(139); - layers_.emplace_back(0, layer_end_); +// layers_.emplace_back(0, layer_end_); + layers_.emplace_back(0); + layers_.emplace_back(layer_end_); +} + +template +LayerQueue::~LayerQueue() { + // delete []data_; + std::free(data_); } template -void LayerQueue::emplace(T item) { - data_[queue_end_] = item; +void LayerQueue::emplace(T node) { + data_[queue_end_] = node; ++queue_end_; } @@ -30,7 +49,8 @@ void LayerQueue::next() { if (queue_begin_ == layer_end_ && !is_ending()) { layer_begin_ = layer_end_; layer_end_ = queue_end_; - layers_.emplace_back(layer_begin_, layer_end_); +// layers_.emplace_back(layer_begin_, layer_end_); + layers_.emplace_back(layer_end_); } } @@ -44,13 +64,40 @@ template return queue_begin_ == layer_begin_; } +//template +//std::vector LayerQueue::layer_cases() const { +// std::vector layer_cases; +// for (size_t offset = layer_begin_; offset < layer_end_; ++offset) { +// layer_cases.emplace_back(data_[offset]); +// } +// return layer_cases; +//} + template -std::vector LayerQueue::layer_cases() const { - std::vector layer_cases; - for (size_t offset = layer_begin_; offset < layer_end_; ++offset) { - layer_cases.emplace_back(data_[offset]); +std::vector LayerQueue::last_layer() const { + std::vector layer; + layer.reserve(layer_end_ - layer_begin_); + for (auto offset = layer_begin_; offset < layer_end_; ++offset) { + layer.emplace_back(data_[offset]); // TODO: copy directly + } + return layer; +} + +template +std::vector> LayerQueue::all_layers() const { + std::vector> result; + for (size_t i = 0; i < layers_.size() - 1; ++i) { + size_t begin = layers_[i]; + size_t end = layers_[i + 1]; + + std::vector layer {}; + layer.reserve(end - begin); + for (auto offset = begin; offset < end; ++offset) { + layer.emplace_back(data_[offset]); // TODO: copy directly + } + result.emplace_back(layer); } - return layer_cases; + return result; } } // namespace klotski diff --git a/src/core/fast_cal/layer_queue.h b/src/core/fast_cal/layer_queue.h index 7764848..ffdc749 100644 --- a/src/core/fast_cal/layer_queue.h +++ b/src/core/fast_cal/layer_queue.h @@ -3,39 +3,55 @@ #pragma once #include -#include namespace klotski { template -class LayerQueue { +class LayerQueue final { public: - LayerQueue(size_t reserve, std::initializer_list first_layer); + ~LayerQueue(); - void emplace(T item); + /// Construct from first layer cases and reserve size. + LayerQueue(std::initializer_list first_layer, size_t reserve); - T current() const; + // ------------------------------------------------------------------------------------- // + /// Pop the head of the queue. void next(); + /// Obtain the current working node. + T current() const; + + /// Emplace new node at the end of the queue. + void emplace(T node); + + // ------------------------------------------------------------------------------------- // + + /// Whether the queue is empty. [[nodiscard]] bool is_ending() const; + /// Whether the queue front is on new layer. [[nodiscard]] bool is_new_layer() const; - std::vector layer_cases() const; + // ------------------------------------------------------------------------------------- // - // TODO: allow export all layers + /// Get the nodes of the last layer. + std::vector last_layer() const; -private: - size_t queue_begin_ {0}; - size_t queue_end_ {0}; + /// Get all the nodes of each layer. + std::vector> all_layers() const; - size_t layer_begin_ {0}; - size_t layer_end_ {0}; + // ------------------------------------------------------------------------------------- // + +private: + size_t layer_begin_, layer_end_; + size_t queue_begin_, queue_end_; - std::vector data_ {}; + // std::vector data_ {}; + T *data_ {nullptr}; - std::vector> layers_ {}; + std::vector layers_ {}; + // std::vector> layers_ {}; }; } // namespace klotski diff --git a/src/core/main.cc b/src/core/main.cc index 3cad9ac..b313b1c 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -48,7 +48,22 @@ int main() { auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); klotski::fast_cal::FastCalPro fc {code}; - std::cout << fc.solve().value() << std::endl; + + // std::cout << fc.solve().value() << std::endl; + + // for (auto x : fc.solve_multi()) { + // std::cout << x << std::endl; + // } + + // for (auto x : fc.furthest()) { + // std::cout << x << std::endl; + // } + + fc.furthest(); + for (const auto &layer : fc.exports()) { + std::cout << layer.size() << std::endl; + } + std::cout << "layer num: " << fc.exports().size() << std::endl; // for (int i = 0; i < 10000000; ++i) { // MaskMover mover([](uint64_t code, uint64_t mask) {