solver: construct odd-order solutions
Avoid repeating the exponential search for odd orders at least nine. Search the even predecessor, translate its row-major placements to the enlarged board, and tile the new border. Keep direct search and construction explicit so benchmarks can report their costs separately. Verify the routed order-9 result independently and require its search counters to match order 8. Tests: Release, Debug, ASan and UBSan CTest (8 passed each) Refs: #6
This commit was merged in pull request #21.
This commit is contained in:
+37
-9
@@ -20,6 +20,37 @@ namespace {
|
||||
return std::chrono::duration<double>(end - begin).count();
|
||||
}
|
||||
|
||||
struct TimedSolution {
|
||||
Results result;
|
||||
double search_seconds;
|
||||
double construction_seconds;
|
||||
};
|
||||
|
||||
auto solve(std::uint64_t order, bool instrument, SearchCounters &counters)
|
||||
-> TimedSolution {
|
||||
auto const predecessor_order =
|
||||
uses_odd_construction(order) ? order - 1 : order;
|
||||
auto const search_begin = Clock::now();
|
||||
auto predecessor =
|
||||
instrument
|
||||
? search_solution_instrumented(predecessor_order, counters)
|
||||
: search_solution(predecessor_order);
|
||||
auto const search_end = Clock::now();
|
||||
|
||||
auto const construction_begin = Clock::now();
|
||||
auto result = uses_odd_construction(order)
|
||||
? construct_odd_solution(order, std::move(predecessor))
|
||||
: std::move(predecessor);
|
||||
auto const construction_end = Clock::now();
|
||||
return {
|
||||
std::move(result),
|
||||
seconds(search_begin, search_end),
|
||||
uses_odd_construction(order)
|
||||
? seconds(construction_begin, construction_end)
|
||||
: 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
auto valid(std::uint64_t order, Results const &result) -> bool {
|
||||
auto const expected = triangle_num(order);
|
||||
if (result.length() != expected) {
|
||||
@@ -71,19 +102,16 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
SearchCounters counters;
|
||||
auto const solve_begin = Clock::now();
|
||||
auto result = instrument ? find_solution_instrumented(order, counters)
|
||||
: find_solution(order);
|
||||
auto const solve_end = Clock::now();
|
||||
auto timed = solve(order, instrument, counters);
|
||||
|
||||
auto const validation_begin = Clock::now();
|
||||
auto const validation_ok = valid(order, result);
|
||||
auto const validation_ok = valid(order, timed.result);
|
||||
auto const validation_end = Clock::now();
|
||||
|
||||
auto const render_begin = Clock::now();
|
||||
std::ostringstream rendered;
|
||||
auto *const old_buffer = std::cout.rdbuf(rendered.rdbuf());
|
||||
result.output();
|
||||
timed.result.output();
|
||||
std::cout.rdbuf(old_buffer);
|
||||
auto const render_end = Clock::now();
|
||||
|
||||
@@ -92,10 +120,10 @@ int main(int argc, char **argv) {
|
||||
<< "{\"schema_version\":1"
|
||||
<< ",\"order\":" << order
|
||||
<< ",\"instrumented\":" << boolean(instrument)
|
||||
<< ",\"solved\":" << boolean(!result.squares().empty())
|
||||
<< ",\"solved\":" << boolean(!timed.result.squares().empty())
|
||||
<< ",\"valid\":" << boolean(validation_ok)
|
||||
<< ",\"timing_seconds\":{\"solve\":" << seconds(solve_begin, solve_end)
|
||||
<< ",\"construction\":0"
|
||||
<< ",\"timing_seconds\":{\"solve\":" << timed.search_seconds
|
||||
<< ",\"construction\":" << timed.construction_seconds
|
||||
<< ",\"validation\":" << seconds(validation_begin, validation_end)
|
||||
<< ",\"render\":" << seconds(render_begin, render_end) << "}"
|
||||
<< ",\"counters\":{\"search_nodes\":" << counters.search_nodes
|
||||
|
||||
Reference in New Issue
Block a user