mirror of https://github.com/dnomd343/klotski.git
				
				
			
				 3 changed files with 66 additions and 128 deletions
			
			
		@ -1,99 +1,81 @@ | 
				
			|||
#include <iostream> | 
				
			|||
 | 
				
			|||
#include "cases.h" | 
				
			|||
 | 
				
			|||
/// Filter cases with different type_id from AllCases.
 | 
				
			|||
static std::vector<std::vector<CommonCode>> build_all_cases() { | 
				
			|||
    std::vector<std::vector<CommonCode>> codes; | 
				
			|||
    for (auto code : AllCases::instance().fetch().codes()) { | 
				
			|||
        const auto type_id = to_type_id(cal_block_num(code.unwrap())); | 
				
			|||
        if (type_id >= codes.size()) { | 
				
			|||
            codes.resize(type_id + 1); | 
				
			|||
        } | 
				
			|||
        codes[type_id].emplace_back(code); | 
				
			|||
    } | 
				
			|||
    return codes; | 
				
			|||
} | 
				
			|||
// TODO: multi-threads builder
 | 
				
			|||
 | 
				
			|||
std::vector<CommonCode> extend_cases(CommonCode seed) { | 
				
			|||
    auto raw_codes = klotski::cases::Group::extend(seed.to_raw_code()); // TODO: using inner build process
 | 
				
			|||
/// Extend ordered Group from the specified CommonCode seed.
 | 
				
			|||
static std::vector<CommonCode> extend_cases(CommonCode seed) { | 
				
			|||
    // TODO: using inner build process
 | 
				
			|||
    auto raw_codes = klotski::cases::Group::extend(seed.to_raw_code()); | 
				
			|||
    std::vector<CommonCode> common_codes {raw_codes.begin(), raw_codes.end()}; | 
				
			|||
    std::ranges::sort(common_codes.begin(), common_codes.end()); | 
				
			|||
    return common_codes; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
std::vector<CommonCode> remove_sub(const std::vector<CommonCode> &all, const std::vector<CommonCode> &sub) { | 
				
			|||
    std::vector<CommonCode> tmp; | 
				
			|||
    tmp.reserve(all.size() - sub.size()); | 
				
			|||
    std::ranges::set_difference(all.begin(), all.end(), sub.begin(), sub.end(), std::back_inserter(tmp)); | 
				
			|||
    return tmp; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
/// Split Groups from the specified ordered list of CommonCodes.
 | 
				
			|||
static std::vector<std::vector<CommonCode>> split_groups(std::vector<CommonCode> codes) { | 
				
			|||
 | 
				
			|||
    std::vector<std::vector<CommonCode>> groups; | 
				
			|||
 | 
				
			|||
    while (!codes.empty()) { | 
				
			|||
        auto sub = extend_cases(codes[0]); | 
				
			|||
        auto group = extend_cases(codes[0]); // sorted array
 | 
				
			|||
        groups.emplace_back(group); | 
				
			|||
 | 
				
			|||
        groups.emplace_back(sub); | 
				
			|||
        codes = remove_sub(codes, sub); | 
				
			|||
        std::vector<CommonCode> remain; | 
				
			|||
        remain.reserve(codes.size() - group.size()); | 
				
			|||
        std::ranges::set_difference(codes.begin(), codes.end(), group.begin(), group.end(), std::back_inserter(remain)); | 
				
			|||
        codes = remain; // for next loop
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    std::ranges::stable_sort(groups.begin(), groups.end(), [](const std::vector<CommonCode> &g1, const std::vector<CommonCode> &g2) { | 
				
			|||
        return g1.size() > g2.size(); | 
				
			|||
    std::ranges::stable_sort(groups.begin(), groups.end(), [](const auto &lhs, const auto &rhs) { | 
				
			|||
        return lhs.size() > rhs.size(); // sort with group size
 | 
				
			|||
    }); | 
				
			|||
 | 
				
			|||
    return groups; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
/// Filter cases with different type_id from AllCases.
 | 
				
			|||
static const std::vector<std::vector<CommonCode>>& group_union_data() { | 
				
			|||
    static auto data = [] { | 
				
			|||
        std::vector<std::vector<CommonCode>> codes; | 
				
			|||
        codes.resize(block_nums().size()); | 
				
			|||
        for (auto code: AllCases::instance().fetch().codes()) { | 
				
			|||
            codes[to_type_id(cal_block_num(code.unwrap()))].emplace_back(code); | 
				
			|||
        } | 
				
			|||
        return codes; | 
				
			|||
    }(); | 
				
			|||
    return data; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
// TODO: static data of `build_all_cases`
 | 
				
			|||
/// Construct all valid klotski Groups in different GroupUnion.
 | 
				
			|||
static const std::vector<std::vector<std::vector<CommonCode>>>& group_data() { | 
				
			|||
    static auto data = [] { | 
				
			|||
        std::vector<std::vector<std::vector<CommonCode>>> groups; | 
				
			|||
        groups.reserve(group_union_num()); | 
				
			|||
        for (uint32_t type_id = 0; type_id < group_union_num(); ++type_id) { | 
				
			|||
            groups.emplace_back(split_groups(group_union_cases(type_id))); | 
				
			|||
        } | 
				
			|||
        return groups; | 
				
			|||
    }(); | 
				
			|||
    return data; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
uint32_t group_union_num() { | 
				
			|||
    static auto data = build_all_cases(); | 
				
			|||
    return data.size(); | 
				
			|||
    return group_union_data().size(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
const std::vector<CommonCode>& group_union_cases(const uint32_t type_id) { | 
				
			|||
    static auto data = build_all_cases(); | 
				
			|||
    if (type_id < data.size()) { | 
				
			|||
        return data[type_id]; | 
				
			|||
uint32_t group_num(uint32_t type_id) { | 
				
			|||
    if (type_id < group_data().size()) { | 
				
			|||
        return group_data()[type_id].size(); | 
				
			|||
    } | 
				
			|||
    std::abort(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
// TODO: multi-threads builder
 | 
				
			|||
 | 
				
			|||
static std::vector<std::vector<std::vector<CommonCode>>> all_groups_builder() { | 
				
			|||
 | 
				
			|||
    std::vector<std::vector<std::vector<CommonCode>>> data; | 
				
			|||
 | 
				
			|||
    for (uint32_t type_id = 0; type_id < group_union_num(); ++type_id) { | 
				
			|||
 | 
				
			|||
        data.emplace_back(split_groups(group_union_cases(type_id))); | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    return data; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
uint32_t group_num(uint32_t type_id) { | 
				
			|||
    static auto data = all_groups_builder(); | 
				
			|||
    if (type_id < data.size()) { | 
				
			|||
        return data[type_id].size(); | 
				
			|||
const std::vector<CommonCode>& group_union_cases(const uint32_t type_id) { | 
				
			|||
    if (type_id < group_union_data().size()) { | 
				
			|||
        return group_union_data()[type_id]; | 
				
			|||
    } | 
				
			|||
    std::abort(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
const std::vector<CommonCode>& group_cases(uint32_t type_id, uint32_t group_id) { | 
				
			|||
 | 
				
			|||
    static auto data = all_groups_builder(); | 
				
			|||
 | 
				
			|||
    if (type_id < data.size() && group_id < data[type_id].size()) { | 
				
			|||
        return data[type_id][group_id]; | 
				
			|||
    if (type_id < group_data().size() && group_id < group_data()[type_id].size()) { | 
				
			|||
        return group_data()[type_id][group_id]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    std::abort(); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
					Loading…
					
					
				
		Reference in new issue