diff --git a/src/core/group/internal/group.cc b/src/core/group/internal/group.cc index c11b824..bbd4fc9 100644 --- a/src/core/group/internal/group.cc +++ b/src/core/group/internal/group.cc @@ -70,26 +70,51 @@ static RangesUnion extend_demo(Group group, RawCode seed, size_t reserve) { // T cases.emplace(code, mask); codes.emplace_back(code); // new case - auto kk = code.to_horizontal_mirror(); - // if (const auto match = cases.find(kk.unwrap()); match != cases.end()) { - // return; - // } - // cases.emplace(kk, 0); - if (kk != code && cases.try_emplace(kk.unwrap(), 0).second) { - mirror_codes.emplace_back(kk); + auto k1 = code.to_horizontal_mirror(); + if (k1 != code) { + bool ret = cases.try_emplace(k1.unwrap(), 0).second; + if (!ret) { + std::cout << "!!! get unexpect case" << std::endl; // TODO: can we confirm it? + } else { + mirror_codes.emplace_back(k1); + } } + + // auto k2 = code.to_vertical_mirror(); + // if (k2 != code && cases.try_emplace(k2.unwrap(), 0).second) { + // mirror_codes.emplace_back(k2); + // } + + // auto k3 = k2.to_horizontal_mirror(); + // if (k3 != code && cases.try_emplace(k3.unwrap(), 0).second) { + // mirror_codes.emplace_back(k3); + // } }); uint64_t offset = 0; codes.emplace_back(seed); cases.emplace(seed, 0); // without mask - auto pp = seed.to_horizontal_mirror(); - if (pp != seed) { - mirror_codes.emplace_back(seed.to_horizontal_mirror()); - cases.emplace(seed.to_horizontal_mirror(), 0); + auto p1 = seed.to_horizontal_mirror(); + if (p1 != seed) { + mirror_codes.emplace_back(p1); + cases.emplace(p1, 0); } + std::cout << std::format("{} vs {}\n", codes.size(), mirror_codes.size()); + + // auto p2 = seed.to_vertical_mirror(); + // if (p2 != seed) { + // mirror_codes.emplace_back(p2); + // cases.emplace(p2, 0); + // } + + // auto p3 = p2.to_horizontal_mirror(); + // if (p3 != p2) { + // mirror_codes.emplace_back(p3); + // cases.emplace(p3, 0); + // } + while (offset != codes.size()) { auto curr = codes[offset++].unwrap(); core.next_cases(RawCode::unsafe_create(curr), cases.find(curr)->second); @@ -107,13 +132,262 @@ static RangesUnion extend_demo(Group group, RawCode seed, size_t reserve) { // T return result; } +static RangesUnion extend_type_common(RawCode seed, size_t reserve) { + std::vector codes; + phmap::flat_hash_map cases; // + + codes.reserve(reserve); + cases.reserve(reserve * 1.56); + + auto core = MaskMover([&codes, &cases](RawCode code, uint64_t hint) { + if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { + iter->second |= hint; // update hint + return; + } + codes.emplace_back(code); // new case + }); + + uint64_t offset = 0; + codes.emplace_back(seed); + cases.emplace(seed, 0); // without hint + + while (offset != codes.size()) { + auto curr = codes[offset++]; + core.next_cases(curr, cases.find(curr)->second); + } + + RangesUnion result {}; + // TODO: how to reserve + for (auto raw_code : codes) { // TODO: using `std::views::concat` in new std library + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + return result; +} + +static RangesUnion extend_type_hor(RawCode seed, size_t reserve) { + std::vector codes; + std::vector mirrors; + phmap::flat_hash_map cases; // + + codes.reserve(reserve); + mirrors.reserve(reserve); // TODO: cal max size-coff + cases.reserve(reserve * 1.56); + + auto core = MaskMover([&codes, &cases, &mirrors](RawCode code, uint64_t hint) { + if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { + iter->second |= hint; // update hint + return; + } + codes.emplace_back(code); // new case + + const auto k1 = code.to_horizontal_mirror(); + if (k1 != code) { + cases.emplace(k1, 0); // TODO: contain check + mirrors.emplace_back(k1); + } + }); + + uint64_t offset = 0; + codes.emplace_back(seed); + cases.emplace(seed, 0); // without hint + + const auto p1 = seed.to_horizontal_mirror(); + if (p1 != seed) { + mirrors.emplace_back(p1); + cases.emplace(p1, 0); + } + + while (offset != codes.size()) { + auto curr = codes[offset++]; + core.next_cases(curr, cases.find(curr)->second); + } + + RangesUnion result {}; + // TODO: how to reserve + for (auto raw_code : codes) { // TODO: using `std::views::concat` in new std library + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + for (auto raw_code : mirrors) { + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + return result; +} + +static RangesUnion extend_type_ver(RawCode seed, size_t reserve) { + std::vector codes; + std::vector mirrors; + phmap::flat_hash_map cases; // + + codes.reserve(reserve); + mirrors.reserve(reserve); // TODO: cal max size-coff + cases.reserve(reserve * 1.56); + + auto core = MaskMover([&codes, &cases, &mirrors](RawCode code, uint64_t hint) { + if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { + iter->second |= hint; // update hint + return; + } + codes.emplace_back(code); // new case + + const auto k1 = code.to_vertical_mirror(); + if (k1 != code) { + cases.emplace(k1, 0); // TODO: contain check + mirrors.emplace_back(k1); + } + }); + + uint64_t offset = 0; + codes.emplace_back(seed); + cases.emplace(seed, 0); // without hint + + const auto p1 = seed.to_vertical_mirror(); + if (p1 != seed) { + mirrors.emplace_back(p1); + cases.emplace(p1, 0); + } + + while (offset != codes.size()) { + auto curr = codes[offset++]; + core.next_cases(curr, cases.find(curr)->second); + } + + RangesUnion result {}; + // TODO: how to reserve + for (auto raw_code : codes) { // TODO: using `std::views::concat` in new std library + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + for (auto raw_code : mirrors) { + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + return result; +} + +static RangesUnion extend_type_diag(RawCode seed, size_t reserve) { + std::vector codes; + std::vector mirrors; + phmap::flat_hash_map cases; // + + codes.reserve(reserve); + mirrors.reserve(reserve); // TODO: cal max size-coff + cases.reserve(reserve * 1.56); + + auto core = MaskMover([&codes, &cases, &mirrors](RawCode code, uint64_t hint) { + if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { + iter->second |= hint; // update hint + return; + } + codes.emplace_back(code); // new case + + const auto k1 = code.to_vertical_mirror().to_horizontal_mirror(); + if (k1 != code) { + cases.emplace(k1, 0); // TODO: contain check + mirrors.emplace_back(k1); + } + }); + + uint64_t offset = 0; + codes.emplace_back(seed); + cases.emplace(seed, 0); // without hint + + const auto p1 = seed.to_vertical_mirror().to_horizontal_mirror(); + if (p1 != seed) { + mirrors.emplace_back(p1); + cases.emplace(p1, 0); + } + + while (offset != codes.size()) { + auto curr = codes[offset++]; + core.next_cases(curr, cases.find(curr)->second); + } + + RangesUnion result {}; + // TODO: how to reserve + for (auto raw_code : codes) { // TODO: using `std::views::concat` in new std library + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + for (auto raw_code : mirrors) { + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + return result; +} + +static RangesUnion extend_type_x(RawCode seed, size_t reserve) { + std::vector codes; + std::vector mirrors; + phmap::flat_hash_map cases; // + + codes.reserve(reserve); + mirrors.reserve(reserve); // TODO: cal max size-coff + cases.reserve(reserve * 1.56); + + auto core = MaskMover([&codes, &cases, &mirrors](RawCode code, uint64_t hint) { + if (const auto [iter, ret] = cases.try_emplace(code, hint); !ret) { + iter->second |= hint; // update hint + return; + } + codes.emplace_back(code); // new case + + const auto k1 = code.to_vertical_mirror(); + mirrors.emplace_back(k1); + cases.emplace(k1, 0); + const auto k2 = code.to_horizontal_mirror(); + if (k2 != code) { + mirrors.emplace_back(k2); + cases.emplace(k2, 0); + const auto p3 = k1.to_horizontal_mirror(); + mirrors.emplace_back(p3); + cases.emplace(p3, 0); + } + }); + + uint64_t offset = 0; + codes.emplace_back(seed); + cases.emplace(seed, 0); // without hint + + const auto p1 = seed.to_vertical_mirror(); + mirrors.emplace_back(p1); + cases.emplace(p1, 0); + const auto p2 = seed.to_horizontal_mirror(); + if (p2 != seed) { + mirrors.emplace_back(p2); + cases.emplace(p2, 0); + const auto p3 = p1.to_horizontal_mirror(); + mirrors.emplace_back(p3); + cases.emplace(p3, 0); + } + + while (offset != codes.size()) { + auto curr = codes[offset++]; + core.next_cases(curr, cases.find(curr)->second); + } + + RangesUnion result {}; + // TODO: how to reserve + for (auto raw_code : codes) { // TODO: using `std::views::concat` in new std library + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + for (auto raw_code : mirrors) { + const auto code = raw_code.to_common_code().unwrap(); + result.ranges(code >> 32).emplace_back(static_cast(code)); + } + return result; +} + // TODO: maybe we can perf with mirror cases RangesUnion Group::cases() const { // TODO: add white list for single-group unions // return GroupUnion::cases directly - auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id()] >> 23); + auto seed = CommonCode::unsafe_create(PATTERN_DATA[flat_id()] >> 23).to_raw_code(); // NOTE: convert as RawCode directly if (toward_ == Toward::B) { @@ -125,10 +399,33 @@ RangesUnion Group::cases() const { seed = seed.to_vertical_mirror().to_horizontal_mirror(); } - // std::cout << seed << std::endl; - auto data = extend_demo(*this, seed.to_raw_code(), size()); + // auto data = extend_type_hor(seed, size()); + // auto data = extend_type_ver(seed, size()); + // auto data = extend_type_diag(seed, size()); + // auto data = extend_type_x(seed, size()); + + RangesUnion data; + if (mirror_type() == MirrorType::Full) { + data = extend_type_x(seed, size()); + } else if (mirror_type() == MirrorType::Horizontal) { + data = extend_type_hor(seed, size()); + } else if (mirror_type() == MirrorType::Vertical) { + data = extend_type_ver(seed, size()); + } else if (mirror_type() == MirrorType::Centro) { + data = extend_type_diag(seed, size()); + } else { + data = extend_type_common(seed, size()); + } + + // auto raw_data = Group_extend_for_cases(seed, size()); + // RangesUnion data {}; + // for (auto raw_code : raw_data) { + // auto common_code = raw_code.to_common_code().unwrap(); + // data.ranges(common_code >> 32).emplace_back(static_cast(common_code)); + // } + for (int head = 0; head < 16; ++head) { - std::stable_sort(data.ranges(head).begin(), data.ranges(head).end()); + std::stable_sort(data.ranges(head).begin(), data.ranges(head).end()); // TODO: maybe using quick_sort } return data; } diff --git a/src/core/main.cc b/src/core/main.cc index b0d9813..b8cfb14 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -52,6 +52,25 @@ int main() { // TODO: maybe we can support `std::format` + // auto group = Group::create(169, 0, Group::Toward::C).value(); + // auto group = Group::create(82, 68, Group::Toward::C).value(); + // auto group = Group::create(189, 279, Group::Toward::A).value(); + // auto kk = group.cases(); + // std::cout << kk.size() << std::endl; + + for (int type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { + for (auto group : GroupUnion::unsafe_create(type_id).groups()) { + // if (group.is_horizontal_mirror()) { + // if (group.is_vertical_mirror()) { + // if (group.mirror_type() == Group::MirrorType::Centro) { + // if (group.mirror_type() == Group::MirrorType::Full) { + // std::cout << group.to_string() << std::endl; + volatile auto kk = group.cases(); + // std::cout << group.size() << std::endl; + // } + } + } + // const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); // const auto solve_1 = CommonCode::unsafe_create(0xDAAF4CC00).to_raw_code(); // const auto solve_2 = CommonCode::unsafe_create(0xDAA7F3000).to_raw_code(); @@ -62,13 +81,13 @@ int main() { // std::cout << backtrack.size() << std::endl; // std::cout << backtrack[0].size() << ", " << backtrack[81].size() << std::endl; - const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); + // const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); // const auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code(); - FastCal fc {code}; + // FastCal fc {code}; // std::cout << fc.solve().value() << std::endl; - std::cout << fc.backtrack(fc.solve().value()).size() << std::endl; + // std::cout << fc.backtrack(fc.solve().value()).size() << std::endl; // for (const auto x : fc.solve_multi()) { // std::cout << x.to_common_code() << std::endl; @@ -178,6 +197,7 @@ int main() { // std::cout << (int)gp.mirror_type() << std::endl; #if defined(__clang__) + // std::cerr << (std::chrono::system_clock::now() - start).count() << "us" << std::endl; std::cerr << (std::chrono::system_clock::now() - start).count() / 1000 << "ms" << std::endl; #elif defined(__GNUC__) std::cerr << (std::chrono::system_clock::now() - start).count() / 1000000 << "ms" << std::endl;