/* * Copyright (C) 2022 Camden Dixie O'Brien * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with this program. If not, see * . */ #include "solve.h" #include "sud.h" #include #include #include #include #define PROG_UPDATEPRD 20 #define NPUZZLES 256U struct bench_res { double succ_rate; double avg_time_us; double avg_passes; }; static uint32_t getseed(void) { FILE *urandom = fopen("/dev/urandom", "rb"); if (urandom == NULL) fprintf(stderr, "Failed to open /dev/urandom\n"); uint32_t seed = 0; for (unsigned i = 0; i < 4; ++i) seed = seed << 8 | fgetc(urandom); fclose(urandom); return seed; } static void genpuzzles(struct sudoku puzzles_out[NPUZZLES], double fill_prop, bool print_progress) { unsigned i, j, bslen = 0; if (print_progress) fputs("Generating... ", stdout); for (i = 0; i < NPUZZLES; ++i) { if (print_progress && i % PROG_UPDATEPRD == 0) { for (j = 0; j < bslen; ++j) putchar('\b'); bslen = (unsigned)printf("%u%%", 100 * i / NPUZZLES); fflush(stdout); } gen(&puzzles_out[i], fill_prop); } if (print_progress) { for (i = 0; i < bslen; ++i) putchar('\b'); puts("100%"); } } static void runbench(struct sudoku puzzles[NPUZZLES], struct bench_res *res_out) { int res[NPUZZLES]; unsigned i; struct timespec start, end; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); for (i = 0; i < NPUZZLES; ++i) res[i] = solve(&puzzles[i]); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); long secs = end.tv_sec - start.tv_sec; long nanos = end.tv_nsec - start.tv_nsec; if (nanos < 0) { --secs; nanos += 1000000000; } const double tot_micros = 1e6 * (double)secs + (double)nanos / 1e3; unsigned solved = 0, tot_passes = 0; for (i = 0; i < NPUZZLES; ++i) { if (res[i] < 0) continue; if (check(&puzzles[i]) == SOLVED) ++solved; tot_passes += (unsigned long)res[i]; } res_out->succ_rate = (double)solved / NPUZZLES; res_out->avg_time_us = tot_micros / NPUZZLES; res_out->avg_passes = (double)tot_passes / NPUZZLES; } int main(void) { uint32_t seed = getseed(); printf("Seed: %u\n", seed); srand(seed); struct sudoku puzzles[NPUZZLES]; struct bench_res res; genpuzzles(puzzles, 0.33, true); runbench(puzzles, &res); puts("\n SUMMARY\n ======="); printf("Success rate: %.0lf%%\n", 1e2 * res.succ_rate); printf("Average time: %.3lf µs\n", res.avg_time_us); printf("Average n.o. passes: %0.3lf\n", res.avg_passes); return 0; }