This commit is contained in:
Miloslav Ciz 2024-02-26 11:38:00 +01:00
parent a2a9b750ab
commit ec03c1b60c
22 changed files with 1804 additions and 1686 deletions

108
sudoku.md
View file

@ -74,6 +74,114 @@ For a unique solution sudoku we have to check there still exists exactly one sol
The matter of generating sudokus is further complicated by taking into account the difficulty rating of the puzzle.
## Code
Here is a [C](c.md) code that solves sudoku with [brute force](brute_force.md) (note that for too many empty squares it won't be usable as it might run for years):
```
#include <stdio.h>
char sudoku[9 * 9] = // 0s for empty squares
{
9, 3, 1, 0, 5, 7, 2, 6, 0,
6, 5, 0, 9, 1, 8, 3, 4, 7,
4, 7, 8, 6, 3, 2, 1, 9, 5,
7, 1, 5, 2, 6, 0, 4, 8, 3,
3, 0, 6, 5, 8, 1, 7, 2, 9,
2, 8, 9, 7, 0, 3, 6, 5, 1,
5, 6, 7, 3, 9, 0, 8, 1, 2,
8, 2, 0, 1, 7, 5, 9, 3, 6,
1, 9, 3, 8, 2, 6, 5, 0, 4
};
void print(void)
{
puts("-----------------");
for (int i = 0; i < 9 * 9; ++i)
{
putchar('0' + sudoku[i]);
putchar(i % 9 != 8 ? ' ' : '\n');
}
}
int isValid(void) // checks if whole sudoku is valid
{
for (int i = 0; i < 9; ++i)
{
unsigned int m1 = 0, m2 = 0, m3 = 0; // bit masks of each group
char *s1 = sudoku + i, // column
*s2 = sudoku + i * 9, // row
*s3 = sudoku + (i / 3) * (3 * 3 * 3) + (i % 3) * 3; // square
for (int j = 0; j < 9; ++j)
{
m1 |= (1 << (*s1));
m2 |= (1 << (*s2));
m3 |= (1 << (*s3));
s1 += 9;
s2 += 1;
s3 += (j % 3 != 2) ? 1 : 7;
}
if ((m1 != m2) || (m1 != m3) || (m1 != 0x03fe)) // all must be 1111111110
return 0;
}
return 1;
}
int printCounter = 0;
int solve(void) // find first empty square and brute forces all values on it
{
char *square = sudoku;
printCounter++;
if (printCounter % 512 == 0) // just to limit printing speed
print();
for (int j = 0; j < 9 * 9; ++j, ++square) // find first empty square
if (!(*square)) // empty square?
{
while (1) // try all possible values in the square
{
*square = ((*square) + 1) % 10;
if (!(*square)) // overflow to 0 => we tried all values now
break;
if (solve()) // recursively solve the next empty square
return 1;
}
return 0; // no value led to solution => can't be solved
}
// no empty square found, the sudoku is filled
return isValid();
}
int main(void)
{
/* Here we could do some initial attempts at reasoning and filling in
digits by "logic" before getting to brute force -- with too many empty
squares brute force will take forever. However this is left as an
exercise :-) */
int success = solve();
print();
puts(success ? "solved" : "couldn't solve it");
return 0;
}
```
## See Also
- [sudo](sudo.md)