This commit is contained in:
damage 2024-08-20 19:55:03 +02:00
parent 4dd58b42d0
commit c1f4fa8322
2 changed files with 342 additions and 0 deletions

327
sudoku.c Normal file
View File

@ -0,0 +1,327 @@
#include <stdio.h>
#include <stdbool.h>
#define UNDEFINED -1
#define MULTIPLE -2
#define FIELD_UNDEFINED UNDEFINED
#define FIELD_MULTIPLE MULTIPLE
#define VALUE_UNDEFINED UNDEFINED
#define VALUE_MULTIPLE MULTIPLE
#define VALUE_ALREADY_SET -3
// https://en.wikipedia.org/wiki/Sudoku#/media/File:Sudoku_Puzzle_by_L2G-20050714_standardized_layout.svg
/*
int sudoku[9][9] = {
{5,3,0,6,0,0,0,9,8},
{0,7,0,1,9,5,0,0,0},
{0,0,0,0,0,0,0,6,0},
{8,0,0,4,0,0,7,0,0},
{0,6,0,8,0,3,0,2,0},
{0,0,3,0,0,1,0,0,6},
{0,6,0,0,0,0,0,0,0},
{0,0,0,4,1,9,0,8,0},
{2,8,0,0,0,5,0,7,9}
};
*/
// https://www.free-sudoku.com/sudoku.php?dchoix=evil
int sudoku[9][9] = {
{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},
{VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,4,VALUE_UNDEFINED,VALUE_UNDEFINED,7,VALUE_UNDEFINED},
{4,VALUE_UNDEFINED,5,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,8,VALUE_UNDEFINED,VALUE_UNDEFINED},
{VALUE_UNDEFINED,7,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,2,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED},
{VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,1,VALUE_UNDEFINED,VALUE_UNDEFINED,3,VALUE_UNDEFINED,VALUE_UNDEFINED},
{VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,VALUE_UNDEFINED,7,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}
};
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);
for (int i = 0; i < 9; i++) {
scanf("%d", &sudoku[num][i]);
}
}
int calculateQuadrat(int row, int col) {
return (row / 3) * 3 + col / 3;
}
int calculateField(int row, int col) {
return (row % 3) * 3 + col % 3;
}
int calculateRow(int q, int f) {
return (q / 3) * 3 + (f / 3);
}
int calculateCol(int q, int f) {
return (q % 3) * 3 + (f % 3);
}
void printDumpSudoku() {
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] > VALUE_UNDEFINED) {
printf(" %d", sudoku[q][f]);
} else {
printf(" -");
}
}
printf(" |\n");
}
printf("+-------+-------+-------+\n");
}
void printDumpQuadrat(int q[]) {
for (int row = 0; row < 3; row++) {
if (row % 3 == 0) {
printf("+-------+\n");
}
for (int col = 0; col < 3; col++) {
if (col % 3 == 0) {
if (col != 0) {
printf(" ");
}
printf("|");
}
int f = calculateField(row, col);
printf(" %d", q[f]);
}
printf(" |\n");
}
printf("+-------+\n");
}
// 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] == 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] == val) {
return true;
}
}
return false;
}
// special version of isInRow where it checks if the value
// has to be in the row in special quadrat except the one
// we are currently looking at
bool isOnlyInOneRowQuadrat(int notThisQuadrat, int row, int val) {
int initQ = calculateQuadrat(row, 0);
for (int q = initQ; q < initQ + 3; q++) {
if (q == notThisQuadrat) {
continue;
}
bool skipQuadrat = false;
bool possibleRowFound = false;
for (int f = 0; f < 9 && !skipQuadrat; f++) {
int r = calculateRow(q, f);
int c = calculateCol(q, f);
if (sudoku[q][f] == val) {
if (r == row) {
return true;
} else {
skipQuadrat = true;
continue;
}
} else if (sudoku[q][f] <= VALUE_UNDEFINED && !isInRow(r, val) && !isInCol(c, val)) {
if (r != row) {
return false;
} else {
possibleRowFound = true;
}
} else {
// field is either already set to another value or value is present in current row or col
// either way, this field is not a possible option for the value
}
}
if (!skipQuadrat && possibleRowFound) {
// we found a possible field in row which may be filled with val
// and we didn't hit any abort condition for current quadrat
return true;
}
}
// we didn't found a possible field in row and we didn't hit any
// abort condition. This is may happen if val is already set in bot
// quadrats but not in searched row
return false;
}
// special version of isInCol where it checks if the value
// has to be in the col in special quadrat except the one
// we are currently looking at
bool isOnlyInOneColQuadrat(int notThisQuadrat, int col, int val) {
int initQ = calculateQuadrat(0, col);
for (int q = initQ; q <= initQ + 6; q += 3) {
if (q == notThisQuadrat) {
continue;
}
bool skipQuadrat = false;
bool possibleColFound = false;
for (int f = 0; f < 9 && !skipQuadrat; f++) {
int r = calculateRow(q, f);
int c = calculateCol(q, f);
if (sudoku[q][f] == val) {
if (c == col) {
return true;
} else {
skipQuadrat = true;
continue;
}
} else if (sudoku[q][f] <= VALUE_UNDEFINED && !isInRow(r, val) && !isInCol(c, val)) {
if (c != col) {
return false;
} else {
possibleColFound = true;
}
} else {
// field is either already set to another value or value is present in current row or col
// either way, this field is not a possible option for the value
}
}
if (!skipQuadrat && possibleColFound) {
// we found a possible field in row which may be filled with val
// and we didn't hit any abort condition for current quadrat
return true;
}
}
// we didn't found a possible field in row and we didn't hit any
// abort condition. This is may happen if val is already set in bot
// quadrats but not in searched row
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] == val) {
return true;
}
}
return false;
}
void setValue(int q, int f, int val) {
sudoku[q][f] = val;
printf("=> setting %d in Q %d; F %d\n", val, q, f);
printDumpSudoku();
}
int main() {
printDumpSudoku();
bool somethingChanged;
do {
somethingChanged = false;
for (int q = 0; q < 9; q++) {
int possbileVal[9] = {
VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED,
VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED,
VALUE_UNDEFINED, VALUE_UNDEFINED, VALUE_UNDEFINED
};
for (int val = 1; val <= 9; val++) {
if (isInQuadrat(q, val)) {
continue;
}
int possibleField = FIELD_UNDEFINED;
for (int f = 0; f < 9; f++) {
int row = calculateRow(q, f);
int col = calculateCol(q, f);
// look for val in every row and col
// cache evaluation of isInRow and isInCol
if (sudoku[q][f] <= VALUE_UNDEFINED
&& !(isInRow(row, val) || isOnlyInOneRowQuadrat(q, row, val))
&& !(isInCol(col, val) || isOnlyInOneColQuadrat(q, col, val))) {
// && !isInRow(row, val)
// && !isInCol(col, val)) {
if (possibleField == FIELD_UNDEFINED) {
possibleField = f;
} else {
possibleField = FIELD_MULTIPLE;
}
if (possbileVal[f] == VALUE_UNDEFINED) {
possbileVal[f] = val;
} else if (possbileVal[f] > VALUE_UNDEFINED) {
possbileVal[f] = VALUE_MULTIPLE;
} else {
// already set to multiple or any other meta information
}
}
}
// found possible field? set val
if (possibleField > FIELD_UNDEFINED) {
setValue(q, possibleField, val);
somethingChanged = true;
}
}
// check if only one field is left undefined -> hast to be the one special value
int undefinedFound = VALUE_UNDEFINED;
for (int f = 0; f < 9; f++) {
// keep in mind that sudoku array might have changed since evaluation
// -> ignore already set values
if (sudoku[q][f] > VALUE_UNDEFINED) {
continue;
}
if (possbileVal[f] > VALUE_UNDEFINED) {
setValue(q, f, possbileVal[f]);
somethingChanged = true;
} else {
// set to undefined, multiple or any other meta information
}
}
}
} while (somethingChanged);
// next step: muss in Feld X sein, weil alle anderen Felder irgendwie anders belegt sein müssen (aber noch nicht sind)
}

15
test.c Normal file
View File

@ -0,0 +1,15 @@
#include <stdio.h>
int main() {
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
printf("row: %d col: %d Q: %d F: %d\n", row, col, (row / 3) * 3 + col / 3, (row % 3) * 3 + col % 3);
}
}
for (int q = 0; q < 9; q++) {
for (int f = 0; f < 9; f++) {
printf("Q: %d F: %d row: %d col: %d\n", q, f, (q / 3) * 3 + (f / 3), (q % 3) * 3 + (f % 3));
}
}
}