Compare commits

...
3 Commits
Author SHA1 Message Date
damage 59a399b75a ignore a.out 2026-07-24 20:41:22 +02:00
damage 6fe3c5c188 add step description 2026-07-24 20:41:07 +02:00
damage 8d9c1ae088 bruteforce sudoku solver 2026-07-24 20:40:31 +02:00
3 changed files with 240 additions and 7 deletions
+1
View File
@@ -9,3 +9,4 @@
sudoku sudoku
test test
a.out
+216
View File
@@ -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;
}
+21 -5
View File
@@ -27,6 +27,7 @@ int sudoku[9][9] = {
*/ */
// https://www.free-sudoku.com/sudoku.php?dchoix=evil // https://www.free-sudoku.com/sudoku.php?dchoix=evil
/*
int sudoku[9][9] = { int sudoku[9][9] = {
{VALUE_UNDEFINED,1,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED}, {VALUE_UNDEFINED,1,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED},
{3,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,8,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED}, {3,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,8,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED},
@@ -38,6 +39,19 @@ int sudoku[9][9] = {
{1,VALUE_UNDEFINED,VALUE_UNDEFINED,6,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED}, {1,VALUE_UNDEFINED,VALUE_UNDEFINED,6,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED},
{5,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,8,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED} {5,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,8,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED}
}; };
*/
int sudoku[9][9] = {
{5, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 1, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED},
{VALUE_UNDEFINED, VALUE_UNDEFINED, 4, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 1, VALUE_UNDEFINED, 2},
{7, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 3, VALUE_UNDEFINED, VALUE_UNDEFINED, 5, VALUE_UNDEFINED},
{VALUE_UNDEFINED, VALUE_UNDEFINED, 7, 3, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 6, VALUE_UNDEFINED},
{VALUE_UNDEFINED, 2, VALUE_UNDEFINED, VALUE_UNDEFINED, 6, VALUE_UNDEFINED, VALUE_UNDEFINED, 4, VALUE_UNDEFINED},
{VALUE_UNDEFINED, 9, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 8, 3, VALUE_UNDEFINED, VALUE_UNDEFINED},
{VALUE_UNDEFINED, 8, VALUE_UNDEFINED, VALUE_UNDEFINED, 4, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 2},
{4, VALUE_UNDEFINED, 6, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 7, VALUE_UNDEFINED, VALUE_UNDEFINED},
{VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 1, VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED, 9}
};
void readQ(int num) { void readQ(int num) {
printf("Enter every number of Q%d from left top to right bottom. Use `0` if on no initial value:\n", num + 1); printf("Enter every number of Q%d from left top to right bottom. Use `0` if on no initial value:\n", num + 1);
@@ -225,9 +239,9 @@ bool isInQuadrat(int q, int val) {
return false; return false;
} }
void setValue(int q, int f, int val) { void setValue(int q, int f, int val, char* rule) {
sudoku[q][f] = val; sudoku[q][f] = val;
printf("=> setting %d in Q %d; F %d\n", val, q, f); printf("=> setting %d in Q %d; F %d (%s)\n", val, q, f, rule);
//printDumpSudoku(); //printDumpSudoku();
} }
@@ -276,12 +290,14 @@ int main() {
}; };
for (int val = 1; val <= 9; val++) { for (int val = 1; val <= 9; val++) {
// val is already set in quadrat, go ahead
if (isInQuadrat(q, val)) { if (isInQuadrat(q, val)) {
continue; continue;
} }
int possibleField = FIELD_UNDEFINED; int possibleField = FIELD_UNDEFINED;
for (int f = 0; f < 9; f++) { for (int f = 0; f < 9; f++) {
// calculate row and col of current field in quadrant
int row = calculateRow(q, f); int row = calculateRow(q, f);
int col = calculateCol(q, f); int col = calculateCol(q, f);
@@ -310,12 +326,12 @@ int main() {
// found possible field? set val // found possible field? set val
if (possibleField > FIELD_UNDEFINED) { if (possibleField > FIELD_UNDEFINED) {
setValue(q, possibleField, val); setValue(q, possibleField, val, "standard col/row check");
somethingChanged = true; somethingChanged = true;
} }
} }
// check if only one field is left undefined -> hast to be the one special value // check if only one field is left undefined -> has to be the one special value
for (int f = 0; f < 9; f++) { for (int f = 0; f < 9; f++) {
// keep in mind that sudoku array might have changed since evaluation // keep in mind that sudoku array might have changed since evaluation
// -> ignore already set values // -> ignore already set values
@@ -324,7 +340,7 @@ int main() {
} }
if (possbileVal[f] > VALUE_UNDEFINED) { if (possbileVal[f] > VALUE_UNDEFINED) {
setValue(q, f, possbileVal[f]); setValue(q, f, possbileVal[f], "every other value is not possible here");
somethingChanged = true; somethingChanged = true;
} else { } else {
// set to undefined, multiple or any other meta information // set to undefined, multiple or any other meta information