bruteforce sudoku solver
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user