Compare commits

..

1 Commits
c89 ... main

Author SHA1 Message Date
ee49b1f637 Fix eval target in Makefile 2024-07-31 11:27:08 +01:00
7 changed files with 59 additions and 71 deletions

View File

@ -16,7 +16,7 @@
.POSIX: .POSIX:
CFLAGS += -std=c89 -pedantic -Wall -Wextra CFLAGS += -std=c11 -pedantic -Wall -Wextra
CFLAGS += -O3 -flto CFLAGS += -O3 -flto
CFLAGS += -D_XOPEN_SOURCE=700 CFLAGS += -D_XOPEN_SOURCE=700
CFLAGS += -march=native CFLAGS += -march=native
@ -32,13 +32,15 @@ default: sudoku eval
sudoku: $(OBJ) sudoku: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $@ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o $@
eval: eval.c ds.h
$(CC) $(CFLAGS) $(LDFLAGS) eval.c -o $@
clean: clean:
rm -f sudoku eval genlut *.o lut.c rm -f sudoku eval genlut *.o lut.c
lut.c: genlut lut.c: genlut
./genlut > $@ ./genlut > $@
eval.o: ds.h
main.o: sud.h solve.h ds.h main.o: sud.h solve.h ds.h
sud.o: sud.h lut.h sud.o: sud.h lut.h
solve.o: solve.h lut.h solve.o: solve.h lut.h

22
eval.c
View File

@ -28,25 +28,21 @@
int main(void) int main(void)
{ {
FILE *rfp, *sfp; FILE *rfp = fopen(RESNAME, "rb");
unsigned solved = 0, errors = 0, i, j;
char res[NCELLS], sol[NCELLS];
int allcells;
double pc;
rfp = fopen(RESNAME, "rb");
if (!rfp) { if (!rfp) {
fputs("Failed to open results file\n", stderr); fputs("Failed to open results file\n", stderr);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
sfp = fopen(SOLNAME, "rb"); FILE *sfp = fopen(SOLNAME, "rb");
if (!sfp) { if (!sfp) {
fputs("Failed to open solutions file\n", stderr); fputs("Failed to open solutions file\n", stderr);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
for (i = 0; i < NPUZZ; ++i) { unsigned solved = 0, errors = 0;
char res[NCELLS], sol[NCELLS];
for (unsigned i = 0; i < NPUZZ; ++i) {
if (fread(&res, sizeof(char), NCELLS, rfp) != NCELLS) { if (fread(&res, sizeof(char), NCELLS, rfp) != NCELLS) {
fprintf(stderr, "Failed to read result #%u\n", i); fprintf(stderr, "Failed to read result #%u\n", i);
return EXIT_FAILURE; return EXIT_FAILURE;
@ -56,10 +52,10 @@ int main(void)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
allcells = 1; bool allcells = true;
for (j = 0; j < NCELLS; ++j) { for (unsigned j = 0; j < NCELLS; ++j) {
if (res[j] != sol[j]) { if (res[j] != sol[j]) {
allcells = 0; allcells = false;
if (res[j] != '0') if (res[j] != '0')
++errors; ++errors;
} }
@ -68,7 +64,7 @@ int main(void)
++solved; ++solved;
} }
pc = 1e2 * (double)solved / (double)NPUZZ; double pc = 1e2 * (double)solved / (double)NPUZZ;
printf("%u/%u (%.2f%%) solved, %u errors\n", solved, NPUZZ, pc, errors); printf("%u/%u (%.2f%%) solved, %u errors\n", solved, NPUZZ, pc, errors);
fclose(rfp); fclose(rfp);

View File

@ -25,11 +25,10 @@
static void prlut(const char *name, unsigned lut[NCELLS][NDIGITS - 1]) static void prlut(const char *name, unsigned lut[NCELLS][NDIGITS - 1])
{ {
unsigned i, j;
printf("const unsigned %s[NCELLS][NDIGITS - 1] = {\n", name); printf("const unsigned %s[NCELLS][NDIGITS - 1] = {\n", name);
for (i = 0; i < NCELLS; ++i) { for (unsigned i = 0; i < NCELLS; ++i) {
fputs("\t{ ", stdout); printf("\t[%2u] = { ", i);
for (j = 0; j < NDIGITS - 1; ++j) { for (unsigned j = 0; j < NDIGITS - 1; ++j) {
printf("%2u", lut[i][j]); printf("%2u", lut[i][j]);
if (j != NDIGITS - 2) if (j != NDIGITS - 2)
putchar(','); putchar(',');
@ -45,14 +44,14 @@ int main(void)
unsigned rowidx_lut[NCELLS][NDIGITS - 1]; unsigned rowidx_lut[NCELLS][NDIGITS - 1];
unsigned colidx_lut[NCELLS][NDIGITS - 1]; unsigned colidx_lut[NCELLS][NDIGITS - 1];
unsigned segidx_lut[NCELLS][NDIGITS - 1]; unsigned segidx_lut[NCELLS][NDIGITS - 1];
unsigned rowi, coli, segi, r, c, i, j, sr, sc;
/* Populate tables. */ /* Populate tables. */
for (r = 0; r < NDIGITS; ++r) { unsigned rowi, coli, segi;
for (c = 0; c < NDIGITS; ++c) { for (unsigned r = 0; r < NDIGITS; ++r) {
for (unsigned c = 0; c < NDIGITS; ++c) {
/* Calculate row and column indices. */ /* Calculate row and column indices. */
rowi = coli = 0; rowi = coli = 0;
for (i = 0; i < NDIGITS; ++i) { for (unsigned i = 0; i < NDIGITS; ++i) {
if (i != c) if (i != c)
rowidx_lut[r * NDIGITS + c][rowi++] = r * NDIGITS + i; rowidx_lut[r * NDIGITS + c][rowi++] = r * NDIGITS + i;
if (i != r) if (i != r)
@ -61,10 +60,10 @@ int main(void)
/* Calculate segment indices. */ /* Calculate segment indices. */
segi = 0; segi = 0;
sr = SEGLEN * (r / SEGLEN); const unsigned sr = SEGLEN * (r / SEGLEN);
sc = SEGLEN * (c / SEGLEN); const unsigned sc = SEGLEN * (c / SEGLEN);
for (i = sr; i < sr + SEGLEN; ++i) { for (unsigned i = sr; i < sr + SEGLEN; ++i) {
for (j = sc; j < sc + SEGLEN; ++j) { for (unsigned j = sc; j < sc + SEGLEN; ++j) {
if (i == r && j == c) if (i == r && j == c)
continue; continue;
segidx_lut[r * NDIGITS + c][segi++] = i * NDIGITS + j; segidx_lut[r * NDIGITS + c][segi++] = i * NDIGITS + j;

10
main.c
View File

@ -41,12 +41,12 @@ static char *obuf;
void *threadproc(void *arg) void *threadproc(void *arg)
{ {
unsigned start = CELLPT * (uintptr_t)arg, o; unsigned start = CELLPT * (uintptr_t)arg;
const char *libuf = ibuf + start; const char *libuf = ibuf + start;
char *lobuf = obuf + start; char *lobuf = obuf + start;
struct sudoku sud;
for (o = 0; o < CELLPT; o += NCELLS) { struct sudoku sud;
for (unsigned o = 0; o < CELLPT; o += NCELLS) {
load(&sud, libuf + o); load(&sud, libuf + o);
solve(&sud); solve(&sud);
save(&sud, lobuf + o); save(&sud, lobuf + o);
@ -58,8 +58,6 @@ void *threadproc(void *arg)
int main(void) int main(void)
{ {
int fd; int fd;
pthread_t pool[NTHREADS];
uintptr_t i;
fd = open(IFNAME, O_RDONLY); fd = open(IFNAME, O_RDONLY);
if (fd == -1) { if (fd == -1) {
@ -85,6 +83,8 @@ int main(void)
} }
close(fd); close(fd);
pthread_t pool[NTHREADS];
uintptr_t i;
for (i = 0; i < NTHREADS; ++i) { for (i = 0; i < NTHREADS; ++i) {
if (pthread_create(&pool[i], NULL, threadproc, (void *)i) != 0) if (pthread_create(&pool[i], NULL, threadproc, (void *)i) != 0)
fprintf(stderr, "Failed to create thread #%lu\n", i); fprintf(stderr, "Failed to create thread #%lu\n", i);

15
solve.c
View File

@ -23,8 +23,7 @@
static void setpval(struct sudoku *sud, unsigned i, uint16_t pval) static void setpval(struct sudoku *sud, unsigned i, uint16_t pval)
{ {
unsigned val; for (unsigned val = 0; val < NDIGITS; ++val) {
for (val = 0; val < NDIGITS; ++val) {
if (pval & 1) { if (pval & 1) {
update(sud, i, val); update(sud, i, val);
return; return;
@ -36,11 +35,11 @@ static void setpval(struct sudoku *sud, unsigned i, uint16_t pval)
int solve(struct sudoku *sud) int solve(struct sudoku *sud)
{ {
unsigned n, i, j, val; unsigned n, i, j, val;
int match; bool match;
uint16_t valmask, pvals; uint16_t valmask, pvals;
for (n = 0;; ++n) { for (n = 0;; ++n) {
match = 0; match = false;
for (i = 0; i < NCELLS; ++i) { for (i = 0; i < NCELLS; ++i) {
if (DET(sud->cells[i])) if (DET(sud->cells[i]))
@ -55,7 +54,7 @@ int solve(struct sudoku *sud)
if (pvals & 1) { if (pvals & 1) {
if (pvals == 1) { if (pvals == 1) {
update(sud, i, val); update(sud, i, val);
match = 1; match = true;
goto next_cell; goto next_cell;
} }
break; break;
@ -72,7 +71,7 @@ int solve(struct sudoku *sud)
valmask |= sud->cells[rowidx_lut[i][j]]; valmask |= sud->cells[rowidx_lut[i][j]];
if ((pvals = sud->cells[i] & ~valmask)) { if ((pvals = sud->cells[i] & ~valmask)) {
setpval(sud, i, pvals); setpval(sud, i, pvals);
match = 1; match = true;
continue; continue;
} }
@ -85,7 +84,7 @@ int solve(struct sudoku *sud)
valmask |= sud->cells[colidx_lut[i][j]]; valmask |= sud->cells[colidx_lut[i][j]];
if ((pvals = sud->cells[i] & ~valmask)) { if ((pvals = sud->cells[i] & ~valmask)) {
setpval(sud, i, pvals); setpval(sud, i, pvals);
match = 1; match = true;
continue; continue;
} }
@ -98,7 +97,7 @@ int solve(struct sudoku *sud)
valmask |= sud->cells[segidx_lut[i][j]]; valmask |= sud->cells[segidx_lut[i][j]];
if ((pvals = sud->cells[i] & ~valmask)) { if ((pvals = sud->cells[i] & ~valmask)) {
setpval(sud, i, pvals); setpval(sud, i, pvals);
match = 1; match = true;
continue; continue;
} }

49
sud.c
View File

@ -16,8 +16,8 @@
* <https://www.gnu.org/licenses/>. * <https://www.gnu.org/licenses/>.
*/ */
#include "sud.h"
#include "lut.h" #include "lut.h"
#include "sud.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -28,31 +28,28 @@
static void init(struct sudoku *sud) static void init(struct sudoku *sud)
{ {
unsigned i; for (unsigned i = 0; i < NCELLS; ++i)
for (i = 0; i < NCELLS; ++i)
sud->cells[i] = CELLINIT; sud->cells[i] = CELLINIT;
} }
int load(struct sudoku *sud, const char *ptr) bool load(struct sudoku *sud, const char *ptr)
{ {
unsigned i;
init(sud); init(sud);
for (i = 0; i < NCELLS; ++i) { for (unsigned i = 0; i < NCELLS; ++i) {
if (ptr[i] == '0') if (ptr[i] == '0')
continue; continue;
if (update(sud, i, ptr[i] - '1') != OK) if (update(sud, i, ptr[i] - '1') != OK)
return 0; return false;
} }
return 1; return true;
} }
void save(struct sudoku *sud, char *ptr) void save(struct sudoku *sud, char *ptr)
{ {
unsigned i; for (unsigned i = 0; i < NCELLS; ++i) {
for (i = 0; i < NCELLS; ++i) {
if (DET(sud->cells[i])) if (DET(sud->cells[i]))
*ptr++ = '1' + VAL(sud->cells[i]); *ptr++ = '1' + VAL(sud->cells[i]);
else else
@ -63,11 +60,10 @@ void save(struct sudoku *sud, char *ptr)
enum update_res update(struct sudoku *sud, unsigned i, unsigned val) enum update_res update(struct sudoku *sud, unsigned i, unsigned val)
{ {
const uint16_t clearmask = ~(1 << val); const uint16_t clearmask = ~(1 << val);
unsigned j;
/* Update possible values of cells in same row, column and /* Update possible values of cells in same row, column and
* segment. */ * segment. */
for (j = 0; j < NGROUP; ++j) { for (unsigned j = 0; j < NGROUP; ++j) {
sud->cells[rowidx_lut[i][j]] &= clearmask; sud->cells[rowidx_lut[i][j]] &= clearmask;
sud->cells[colidx_lut[i][j]] &= clearmask; sud->cells[colidx_lut[i][j]] &= clearmask;
sud->cells[segidx_lut[i][j]] &= clearmask; sud->cells[segidx_lut[i][j]] &= clearmask;
@ -83,9 +79,7 @@ enum update_res update(struct sudoku *sud, unsigned i, unsigned val)
void print(const struct sudoku *sud) void print(const struct sudoku *sud)
{ {
unsigned r, c; for (unsigned r = 0; r < NDIGITS; ++r) {
for (r = 0; r < NDIGITS; ++r) {
/* /*
* Print horizontal divider if on a segment boundary (but not * Print horizontal divider if on a segment boundary (but not
* at the start). * at the start).
@ -93,7 +87,7 @@ void print(const struct sudoku *sud)
if (r != 0 && r % SEGLEN == 0) if (r != 0 && r % SEGLEN == 0)
puts("------+-------+------"); puts("------+-------+------");
for (c = 0; c < NDIGITS; ++c) { for (unsigned c = 0; c < NDIGITS; ++c) {
/* /*
* Print vertical divider if on a segment boundary (but * Print vertical divider if on a segment boundary (but
* not at the start). * not at the start).
@ -112,19 +106,17 @@ void print(const struct sudoku *sud)
static void zerocounts(unsigned counts[NDIGITS]) static void zerocounts(unsigned counts[NDIGITS])
{ {
unsigned i; for (unsigned i = 0; i < NDIGITS; ++i)
for (i = 0; i < NDIGITS; ++i)
counts[i] = 0; counts[i] = 0;
} }
static int checkcounts(unsigned counts[NDIGITS]) static bool checkcounts(unsigned counts[NDIGITS])
{ {
unsigned i; for (unsigned i = 0; i < NDIGITS; ++i) {
for (i = 0; i < NDIGITS; ++i) {
if (counts[i] != 1) if (counts[i] != 1)
return 0; return false;
} }
return 1; return true;
} }
enum check_res check(const struct sudoku *sud) enum check_res check(const struct sudoku *sud)
@ -173,14 +165,13 @@ enum check_res check(const struct sudoku *sud)
return SOLVED; return SOLVED;
} }
int filled(const struct sudoku *sud) bool filled(const struct sudoku *sud)
{ {
unsigned r, c; for (unsigned r = 0; r < NDIGITS; ++r) {
for (r = 0; r < NDIGITS; ++r) { for (unsigned c = 0; c < NDIGITS; ++c) {
for (c = 0; c < NDIGITS; ++c) {
if (!(DET(sud->cells[IDX(r, c)]))) if (!(DET(sud->cells[IDX(r, c)])))
return 0; return false;
} }
} }
return 1; return true;
} }

5
sud.h
View File

@ -19,6 +19,7 @@
#ifndef SUD_H #ifndef SUD_H
#define SUD_H #define SUD_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#define SEGLEN 3 #define SEGLEN 3
@ -47,7 +48,7 @@ enum check_res { INCOMPLETE, INCORRECT, SOLVED };
* Read `NCELLS` values from the given pointer and load them into the * Read `NCELLS` values from the given pointer and load them into the
* sudoku. * sudoku.
*/ */
int load(struct sudoku *sud, const char *ptr); bool load(struct sudoku *sud, const char *ptr);
/** /**
* Write the sudoku to the given pointer (`NCELLS` bytes). * Write the sudoku to the given pointer (`NCELLS` bytes).
@ -74,6 +75,6 @@ enum check_res check(const struct sudoku *sud);
/** /**
* Determine whether all the sudoku's cells have been determined. * Determine whether all the sudoku's cells have been determined.
*/ */
int filled(const struct sudoku *sud); bool filled(const struct sudoku *sud);
#endif #endif