From 8d9c1ae088d8208aa7938d6c5b45238541ff5cc3 Mon Sep 17 00:00:00 2001 From: damage Date: Fri, 24 Jul 2026 20:40:31 +0200 Subject: [PATCH] bruteforce sudoku solver --- force.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 force.c diff --git a/force.c b/force.c new file mode 100644 index 0000000..41badf5 --- /dev/null +++ b/force.c @@ -0,0 +1,216 @@ +#include +#include +#include + +#define UNDEFINED -1 + +#define VALUE_TYPE_UNDEFINED UNDEFINED +#define VALUE_TYPE_STATIC 0 +#define VALUE_TYPE_GUESS 1 + +#define COLOR_BLACK 0 +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW 3 +#define COLOR_BLUE 4 +#define COLOR_MAGENTA 5 +#define COLOR_CYAN 6 +#define COLOR_WHITE 7 + +#define COLOR_FG 30 +#define COLOR_BG 40 + +struct Value { + int valueType; + int value; +}; + +/* +int sudoku[9][9] = { + {5, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 1, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 4, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 1, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 2}, + {7, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 3, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 5, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 7, 3, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 6, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, 2, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 6, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 4, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, 9, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 8, 3, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, 8, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 4, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 2}, + {4, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 6, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 7, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 1, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, 9} +}; +*/ +struct Value sudoku[9][9] = { + {{VALUE_TYPE_STATIC, 5}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 1}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 4}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 1}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 2}}, + {{VALUE_TYPE_STATIC, 7}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 3}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 5}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 7}, {VALUE_TYPE_STATIC, 3}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 6}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 2}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 6}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 4}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 9}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 8}, {VALUE_TYPE_STATIC, 3}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 8}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 4}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 2}}, + {{VALUE_TYPE_STATIC, 4}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 6}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 7}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}}, + {{VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 1}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_UNDEFINED, UNDEFINED}, {VALUE_TYPE_STATIC, 9}} +}; + +int calculateRow(int q, int f) { + return (q / 3) * 3 + (f / 3); +} + +int calculateCol(int q, int f) { + return (q % 3) * 3 + (f % 3); +} + +int calculateQuadrat(int row, int col) { + return (row / 3) * 3 + col / 3; +} + +int calculateField(int row, int col) { + return (row % 3) * 3 + col % 3; +} + +// checks if this value is present anywhere in the row +bool isInRow(int row, int val) { + for (int col = 0; col < 9; col++) { + int q = calculateQuadrat(row, col); + int f = calculateField(row, col); + + if (sudoku[q][f].valueType != VALUE_TYPE_UNDEFINED && sudoku[q][f].value == val) { + return true; + } + } + + return false; +} + +// checks if this value is present anywhere in the col +bool isInCol(int col, int val) { + for (int row = 0; row < 9; row++) { + int q = calculateQuadrat(row, col); + int f = calculateField(row, col); + + if (sudoku[q][f].valueType != VALUE_TYPE_UNDEFINED && sudoku[q][f].value == val) { + return true; + } + } + + return false; +} + +// checks if this value is present anywhere in the quadrat +bool isInQuadrat(int q, int val) { + for (int f = 0; f < 9; f++) { + if (sudoku[q][f].valueType != VALUE_TYPE_UNDEFINED && sudoku[q][f].value == val) { + return true; + } + } + + return false; +} + +// check if val is possible value +// i.e. not in row, not in col, not in q +bool check(int q, int f, int val) { + int row = calculateRow(q, f); + int col = calculateCol(q, f); + + return !isInRow(row, val) + && !isInCol(col, val) + && !isInQuadrat(q, val); +} + +void printDumpSudoku() { + printf("\033[H\033[J"); + for (int row = 0; row < 9; row++) { + if (row % 3 == 0) { + printf("+-------+-------+-------+\n"); + } + for (int col = 0; col < 9; col++) { + if (col % 3 == 0) { + if (col != 0) { + printf(" "); + } + printf("|"); + } + + int q = calculateQuadrat(row, col); + int f = calculateField(row, col); + if (sudoku[q][f].valueType != VALUE_TYPE_UNDEFINED) { + int color; + if (sudoku[q][f].valueType == VALUE_TYPE_STATIC) { + color = COLOR_FG + COLOR_BLUE; + } else if (sudoku[q][f].valueType == VALUE_TYPE_GUESS) { + color = COLOR_FG + COLOR_GREEN; + } + printf(" \033[%dm%d\033[0m", color, sudoku[q][f].value); + } else { + printf(" -"); + } + } + printf(" |\n"); + } + printf("+-------+-------+-------+\n"); +} + + +int main() { + long iterations = 0; + long guesses = 0; + for (int q = 0; q < 9; q++) { + for (int f = 0; f < 9; f++) { + if (sudoku[q][f].valueType == VALUE_TYPE_STATIC) { + continue; + } + + iterations++; + + // initialize start value + // might not be 1 if this field was already guessed but we had to go back + // because the guessed value failed later + int startVal; + if (sudoku[q][f].value > UNDEFINED) { + startVal = sudoku[q][f].value + 1; + } else { + startVal = 1; + } + + // loop through values, if one possible value is found (value is neither in row nor in column) + // continue to next field + for (int val = startVal; val <= 9 && sudoku[q][f].valueType == VALUE_TYPE_UNDEFINED; val++) { + if (check(q, f, val)) { + sudoku[q][f].valueType = VALUE_TYPE_GUESS; + sudoku[q][f].value = val; + } + } + + // check if a possible value was found + // if not, go backwards to last guessed value + if (sudoku[q][f].valueType == VALUE_TYPE_UNDEFINED) { + // reset value for next time we get back at + // this position for a guess + sudoku[q][f].value = UNDEFINED; + while (sudoku[q][f].valueType != VALUE_TYPE_GUESS) { + f--; + if (f < 0) { + q--; + if (q < 0) { + fprintf(stderr, "Error: going backwards made q < 0\n"); + return 1; + } + f = 8; + } + } + sudoku[q][f].valueType = VALUE_TYPE_UNDEFINED; + f--; // next iteration will increment f at beginning (for loop) + } else { + // good, possible value found + //printDumpSudoku(); + //usleep(10 * 1000); + guesses++; + } + } + } + + printDumpSudoku(); + printf("Iterations: %ld\n", iterations); + printf("Guesses: %ld\n", guesses); + + return 0; +}