From f51e9a06b054f0972af9fb2eb454a701c711ed08 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Thu, 24 Nov 2022 00:37:48 +0000 Subject: [PATCH] Use uint16_t instead of struct for cell state - Bits 0-8 are the possible values - Bits 9-12 is the concrete value - Bit 15 is 1 if the cell is determined --- solve.c | 16 +++++++++++++--- sud.c | 48 ++++++++++++++++++++++++++---------------------- sud.h | 26 ++++++++++---------------- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/solve.c b/solve.c index 9bda67f..6e6db06 100644 --- a/solve.c +++ b/solve.c @@ -24,6 +24,7 @@ int solve(struct sudoku *sud) { unsigned r, c, n, i, j, val, np, pr, pc; bool match; + uint16_t valmask; for (n = 0;; ++n) { match = false; @@ -31,9 +32,12 @@ int solve(struct sudoku *sud) /* Check if only one place a value can go on each row. */ for (r = 0; r < NDIGITS; ++r) { for (val = 0; val < NDIGITS; ++val) { + valmask = 1 << val; + np = 0; for (c = 0; c < NDIGITS; ++c) { - if (!sud->cells[r][c].det && sud->cells[r][c].pvals[val]) { + if (!(sud->cells[r][c] & DETMASK) + && sud->cells[r][c] & valmask) { pr = r; pc = c; ++np; @@ -52,9 +56,12 @@ int solve(struct sudoku *sud) /* Check if only one place a value can go on each column. */ for (c = 0; c < NDIGITS; ++c) { for (val = 0; val < NDIGITS; ++val) { + valmask = 1 << val; + np = 0; for (r = 0; r < NDIGITS; ++r) { - if (!sud->cells[r][c].det && sud->cells[r][c].pvals[val]) { + if (!(sud->cells[r][c] & DETMASK) + && sud->cells[r][c] & valmask) { pr = r; pc = c; ++np; @@ -73,11 +80,14 @@ int solve(struct sudoku *sud) /* Check if only one place a value can go in each segment. */ for (i = 0; i < NDIGITS; ++i) { for (val = 0; val < NDIGITS; ++val) { + valmask = 1 << val; + np = 0; for (j = 0; j < NDIGITS; ++j) { r = SEGLEN * (i / SEGLEN) + j / SEGLEN; c = SEGLEN * (i % SEGLEN) + j % SEGLEN; - if (!sud->cells[r][c].det && sud->cells[r][c].pvals[val]) { + if (!(sud->cells[r][c] & DETMASK) + && sud->cells[r][c] & valmask) { pr = r; pc = c; ++np; diff --git a/sud.c b/sud.c index f2fc105..b5ff67e 100644 --- a/sud.c +++ b/sud.c @@ -24,20 +24,22 @@ #define MAX_FILL_ATTEMPTS 32 -static void initposs(struct sudoku *sud) +#define CELLINIT 0x01ff + +static void init(struct sudoku *sud) { for (unsigned r = 0; r < NDIGITS; ++r) { for (unsigned c = 0; c < NDIGITS; ++c) { - sud->cells[r][c].det = false; - for (unsigned i = 0; i < NDIGITS; ++i) - sud->cells[r][c].pvals[i] = true; + sud->cells[r][c] = CELLINIT; } } } bool load(struct sudoku *sud, const char *ptr) { - initposs(sud); + + init(sud); + for (unsigned i = 0; i < NCELLS; ++i) { if (ptr[i] == '0') continue; @@ -53,18 +55,20 @@ enum update_res update(struct sudoku *sud, unsigned r, unsigned c, unsigned val) unsigned tr, tc; assert(val < NDIGITS); + const uint16_t clearmask = ~(1 << val); + /* Update possible values of cells in same column. */ for (tr = 0; tr < NDIGITS; ++tr) { - if (tr == r || sud->cells[tr][c].det) + if (tr == r || DET(sud->cells[tr][c])) continue; - sud->cells[tr][c].pvals[val] = false; + sud->cells[tr][c] &= clearmask; } /* Update possible values of cells in same row. */ for (tc = 0; tc < NDIGITS; ++tc) { - if (tc == c || sud->cells[r][tc].det) + if (tc == c || DET(sud->cells[r][tc])) continue; - sud->cells[r][tc].pvals[val] = false; + sud->cells[r][tc] &= clearmask; } /* Update possible values of cells in same segment. */ @@ -72,15 +76,15 @@ enum update_res update(struct sudoku *sud, unsigned r, unsigned c, unsigned val) const unsigned segc0 = SEGLEN * (c / SEGLEN); for (tr = segr0; tr < segr0 + SEGLEN; ++tr) { for (tc = segc0; tc < segc0 + SEGLEN; ++tc) { - if ((tr == r && tc == c) || sud->cells[tr][tc].det) + if ((tr == r && tc == c) || DET(sud->cells[tr][tc])) continue; - sud->cells[tr][tc].pvals[val] = false; + sud->cells[tr][tc] &= clearmask; } } /* Set the cell's value. */ - sud->cells[r][c].det = true; - sud->cells[r][c].val = val; + sud->cells[r][c] |= DETMASK; + sud->cells[r][c] |= val << VALSHIFT; return OK; } @@ -103,8 +107,8 @@ void print(const struct sudoku *sud) if (c != 0 && c % SEGLEN == 0) fputs("| ", stdout); - if (sud->cells[r][c].det) - printf("%u ", sud->cells[r][c].val + 1); + if (DET(sud->cells[r][c])) + printf("%u ", VAL(sud->cells[r][c]) + 1); else fputs(" ", stdout); } @@ -135,9 +139,9 @@ enum check_res check(const struct sudoku *sud) for (r = 0; r < NDIGITS; ++r) { zerocounts(digitcounts); for (c = 0; c < NDIGITS; ++c) { - if (!sud->cells[r][c].det) + if (!DET(sud->cells[r][c])) return INCOMPLETE; - ++digitcounts[sud->cells[r][c].val]; + ++digitcounts[VAL(sud->cells[r][c])]; } if (!checkcounts(digitcounts)) return INCORRECT; @@ -147,9 +151,9 @@ enum check_res check(const struct sudoku *sud) for (c = 0; c < NDIGITS; ++c) { zerocounts(digitcounts); for (r = 0; r < NDIGITS; ++r) { - if (!sud->cells[r][c].det) + if (!DET(sud->cells[r][c])) return INCOMPLETE; - ++digitcounts[sud->cells[r][c].val]; + ++digitcounts[VAL(sud->cells[r][c])]; } if (!checkcounts(digitcounts)) return INCORRECT; @@ -161,9 +165,9 @@ enum check_res check(const struct sudoku *sud) for (j = 0; j < NDIGITS; ++j) { r = 3 * (i / 3) + j / 3; c = 3 * (i % 3) + j % 3; - if (!sud->cells[r][c].det) + if (!DET(sud->cells[r][c])) return INCOMPLETE; - ++digitcounts[sud->cells[r][c].val]; + ++digitcounts[VAL(sud->cells[r][c])]; } if (!checkcounts(digitcounts)) return INCORRECT; @@ -177,7 +181,7 @@ bool filled(const struct sudoku *sud) { for (unsigned r = 0; r < NDIGITS; ++r) { for (unsigned c = 0; c < NDIGITS; ++c) { - if (!sud->cells[r][c].det) + if (!(DET(sud->cells[r][c]))) return false; } } diff --git a/sud.h b/sud.h index 53c159f..0718e9f 100644 --- a/sud.h +++ b/sud.h @@ -20,21 +20,21 @@ #define SUD_H #include +#include #define SEGLEN 3 -#define NDIGITS (SEGLEN * SEGLEN) -#define NCELLS (NDIGITS * NDIGITS) +#define NDIGITS 9 +#define NCELLS 81 -struct cellstate { - bool det; - union { - unsigned val; - bool pvals[NDIGITS]; - }; -}; +#define DETMASK 0x8000 +#define VALSHIFT 9 +#define VALMASK 0x1e00 + +#define DET(x) (x & DETMASK) +#define VAL(x) ((x & VALMASK) >> VALSHIFT) struct sudoku { - struct cellstate cells[NDIGITS][NDIGITS]; + uint16_t cells[NDIGITS][NDIGITS]; }; enum update_res { NOT_ALLOWED, ALREADY_DET, OK }; @@ -47,12 +47,6 @@ enum check_res { INCOMPLETE, INCORRECT, SOLVED }; */ bool load(struct sudoku *sud, const char *ptr); -/** - * Populate the sudoku with some random values. The proportion of - * cells that are filled will be approximately `fill_prop`. - */ -void gen(struct sudoku *sud, double fill_prop); - /** * Attempt to update the cell at row `r`, column `c` to have the value * `val`. Returns `OK` on success, `ALREADY_DET` if the cell is