init ci
This commit is contained in:
parent
4dd58b42d0
commit
c1f4fa8322
327
sudoku.c
Normal file
327
sudoku.c
Normal 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
15
test.c
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user