217 lines
8.9 KiB
C
217 lines
8.9 KiB
C
#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;
|
|
}
|