From 38206fb2d7b6801830192deb401761b0a6ef42a0 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 27 Oct 2024 16:22:42 +0800 Subject: [PATCH] feat: verify with all classic cases --- src/core/main.cc | 87 ++++++++++++++++++++++++++++++++++++++--------- verify/compare.py | 19 +++++++++++ verify/extract.py | 65 +++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 16 deletions(-) create mode 100755 verify/compare.py create mode 100755 verify/extract.py diff --git a/src/core/main.cc b/src/core/main.cc index 0e87a05..9c9eb12 100644 --- a/src/core/main.cc +++ b/src/core/main.cc @@ -49,25 +49,80 @@ int main() { const auto start = std::chrono::system_clock::now(); - // const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); - const auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code(); - FastCal fc {code}; - - // std::cout << fc.solve().value() << std::endl; - - for (const auto x : fc.solve_multi()) { - std::cout << x.to_common_code() << std::endl; + const auto code = CommonCode::unsafe_create(0x1A9BF0C00).to_raw_code(); + // const auto code = CommonCode::unsafe_create(0x4FEA13400).to_raw_code(); + // FastCal fc {code}; + + auto test_0 = [](const CommonCode code) { + std::cout << std::format("[{}]\n", code.to_string()); + std::cout << "--------" << std::endl; + }; + + auto test_1 = [](const RawCode code) { + FastCal fc {code}; + if (const auto solve = fc.solve(); solve.has_value()) { + std::cout << std::format("{} ({})\n", + solve.value().to_common_code().to_string(), fc.backtrack(solve.value()).size()); + } + std::cout << "--------" << std::endl; + for (auto furthest : fc.furthest()) { + std::cout << std::format("{} ({})\n", + furthest.to_common_code().to_string(), fc.backtrack(furthest).size()); + } + std::cout << "--------" << std::endl; + }; + + auto test_2 = [](const RawCode code) { + FastCal fc {code}; + for (auto solve : fc.solve_multi()) { + std::cout << std::format("{} ({})\n", + solve.to_common_code().to_string(), fc.backtrack(solve).size()); + } + std::cout << "--------" << std::endl; + for (auto furthest : fc.furthest()) { + std::cout << std::format("{} ({})\n", + furthest.to_common_code().to_string(), fc.backtrack(furthest).size()); + } + std::cout << "--------" << std::endl; + }; + + auto test_3 = [](const RawCode code) { + for (FastCal fc {code}; auto furthest : fc.furthest()) { + std::cout << std::format("{} ({})\n", + furthest.to_common_code().to_string(), fc.backtrack(furthest).size()); + } + std::cout << "--------" << std::endl; + }; + + // 149 / 154 / 159 / 164 / 169 / 174 + const auto codes = GroupUnion::unsafe_create(174).cases().codes(); + for (size_t index = 0; index < codes.size(); ++index) { + auto common_code = codes[index]; + auto raw_code = common_code.to_raw_code(); + test_0(common_code); + test_1(raw_code); + test_2(raw_code); + test_3(raw_code); + if (index % 100 == 0) { + std::cerr << index << "/" << codes.size() << std::endl; + } } - for (const auto x : fc.furthest()) { - std::cout << x.to_common_code() << std::endl; - } + // std::cout << fc.solve().value() << std::endl; - fc.build_all(); - for (const auto &layer : fc.exports()) { - std::cout << layer.size() << std::endl; - } - std::cout << "layer num: " << fc.exports().size() << std::endl; + // for (const auto x : fc.solve_multi()) { + // std::cout << x.to_common_code() << std::endl; + // } + // + // for (const auto x : fc.furthest()) { + // std::cout << x.to_common_code() << std::endl; + // } + // + // fc.build_all(); + // 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) { diff --git a/verify/compare.py b/verify/compare.py new file mode 100755 index 0000000..0c19a75 --- /dev/null +++ b/verify/compare.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import json + +data_legacy = json.loads(open('legacy.json').read()) +data_next = json.loads(open('data.json').read()) + +assert len(data_legacy) == len(data_next) + +if __name__ == '__main__': + for info in data_legacy: + code = f'{info['code']}00' + info_next = data_next[code] + + assert info['min_solution_step'] == info_next['min_step'] + assert info['farthest_step'] == info_next['max_step'] + + assert info['min_solution_case'] == sorted([x[:7] for x in info_next['solutions']]) + assert info['farthest_case'] == sorted([x[:7] for x in info_next['furthest']]) diff --git a/verify/extract.py b/verify/extract.py new file mode 100755 index 0000000..9fd94a7 --- /dev/null +++ b/verify/extract.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +import re +import json + + +def split_item(raw: str) -> list[tuple[str, int]]: + assert raw[0] == '\n' + matched = [re.match(r'^([\dA-F]{9}) \((\d+)\)$', x) for x in raw[1:].splitlines()] + return [(x[1], int(x[2]) - 1) for x in matched] + + +def load_file(file_name: str) -> dict[str, dict]: + raw = open(file_name).read() + assert raw[0] == '[' + assert raw[-1] == '\n' + + result = {} + for item in raw[1:-1].split('\n['): + item = item.split('--------') + assert len(item) == 7 + assert item[-1] == '' + assert item[2] == item[4] + assert item[2] == item[5] + code = re.match(r'^([\dA-F]{9})]\n$', item[0])[1] + + min_solutions = split_item(item[1]) + assert len(min_solutions) in [0, 1] + solutions = split_item(item[3]) + assert len(set([x[1] for x in solutions])) in [0, 1] + assert len(set([x[0] for x in solutions])) == len(solutions) + + if not min_solutions: + min_step = -1 + assert len(solutions) == 0 + else: + min_step = solutions[0][1] + assert min_solutions[0] in solutions + + furthest = split_item(item[2]) + assert len(set([x[1] for x in furthest])) == 1 + assert len(set([x[0] for x in furthest])) == len(furthest) + + result[code] = { + 'min_step': min_step, + 'max_step': furthest[0][1], + 'solutions': [x[0] for x in solutions], + 'furthest': [x[0] for x in furthest], + } + return result + + +def load_all(files: list[str]) -> dict[str, dict]: + data = {} + [data.update(load_file(x)) for x in files] + data = {x: data[x] for x in sorted(data)} + return data + + +if __name__ == '__main__': + content = json.dumps(load_all([ + 'data_149.txt', 'data_154.txt', 'data_159.txt', + 'data_164.txt', 'data_169.txt', 'data_174.txt' + ])) + print(content)