/*
Sudoku Puzzle generator
(C) Copyright 2007
John Ryland <jryland@invertedlogic.com>
ALL RIGHTS RESERVED
*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int boxTab[81] = {
1,1,1,2,2,2,3,3,3,
1,1,1,2,2,2,3,3,3,
1,1,1,2,2,2,3,3,3,
4,4,4,5,5,5,6,6,6,
4,4,4,5,5,5,6,6,6,
4,4,4,5,5,5,6,6,6,
7,7,7,8,8,8,9,9,9,
7,7,7,8,8,8,9,9,9,
7,7,7,8,8,8,9,9,9
};
unsigned int selected[81];
unsigned int possible[81];
void init()
{
for (int i = 0; i < 81; i++) {
possible[i] = 0x1FFu;
selected[i] = 0;
}
}
void prettyPrint()
{
for (int i = 0; i < 81; i++) {
if (i % 27 == 0)
printf("-------------\n");
if (i % 3 == 0)
printf("|");
printf("%i", selected[i]);
if (i % 9 == 8)
printf("|\n");
}
printf("-------------\n");
}
int onlyOne(int val)
{
for (unsigned int j = 0; j < 9; j++)
if (val == (0x1u << j))
return j + 1;
return 0;
}
void addValue(int pos, unsigned int val)
{
unsigned int mask = 0x1u << (val-1);
if ( (possible[pos] & mask) == 0 )
return;
possible[pos] = ~mask;
selected[pos] = val;
for (int i = 0; i < 81; i++)
if ( !selected[i] ) {
if ( pos/9 == i/9 || pos%9 == i%9 || boxTab[pos] == boxTab[i] ) {
possible[i] &= ~mask;
for (unsigned int j = 0; j < 9; j++)
if (possible[i] == (0x1u << j))
addValue(i, j + 1);
}
}
}
bool addNumbers()
{
for (int i = 0; i < 81; i++) {
if ( !possible[i] )
return false;
while ( selected[i] == 0 )
addValue(i, (rand() % 9) + 1);
}
return true;
}
bool checkValid()
{
for (int j = 0; j < 81; j++)
for (int i = 0; i < 81; i++)
if (i != j && selected[i] && selected[j])
if ( j/9 == i/9 || j%9 == i%9 || boxTab[j] == boxTab[i] )
if ( selected[i] == selected[j] )
return false;
return true;
}
unsigned int puzzleVals[81];
unsigned int puzzleMask[81];
void solverAddValue(int pos, unsigned int val)
{
unsigned int mask = 0x1u << (val-1);
if ( (puzzleMask[pos] & mask) == 0 )
return;
puzzleMask[pos] = ~mask;
puzzleVals[pos] = val;
for (int i = 0; i < 81; i++)
if ( !puzzleVals[i] ) {
if ( pos/9 == i/9 || pos%9 == i%9 || boxTab[pos] == boxTab[i] ) {
puzzleMask[i] &= ~mask;
for (unsigned int j = 0; j < 9; j++)
if (puzzleMask[i] == (0x1u << j))
solverAddValue(i, j + 1);
}
}
}
bool isSolved()
{
for (int j = 0; j < 81; j++)
for (int i = 0; i < 81; i++)
if (i != j)// && puzzleVals[i] && puzzleVals[j])
if ( j/9 == i/9 || j%9 == i%9 || boxTab[j] == boxTab[i] )
if ( puzzleVals[i] == puzzleVals[j] )
return false;
return true;
}
bool canSolve()
{
for (int i = 0; i < 81; i++) {
puzzleVals[i] = selected[i];
puzzleMask[i] = 0x1FFu;
}
for (int i = 0; i < 81; i++) {
if ( puzzleVals[i] ) {
for (int j = 0; j < 81; j++)
if ( !puzzleVals[j] ) {
if ( j/9 == i/9 || j%9 == i%9 || boxTab[j] == boxTab[i] )
puzzleMask[j] &= ~(1 << (puzzleVals[i] - 1));
} else {
puzzleMask[j] = ~(1 << (puzzleVals[i] - 1)); // 0;
}
}
}
for (int i = 0; i < 81; i++)
if ( !puzzleVals[i] ) {
for (unsigned int j = 0; j < 9; j++)
if (puzzleMask[i] == (0x1u << j))
solverAddValue(i, j + 1);
}
return isSolved();
}
bool canRemoveCell(int i)
{
int oldSelected = selected[i];
selected[i] = 0;
bool ret = canSolve();
selected[i] = oldSelected;
return ret;
}
int removeZigZag[81] = {
41,51,31,33,49,81, 1,61,21,
63,19,79, 3,71,11, 9,73,25,
57,55,27,75, 7,65,17,54,78,
4,28,48,24,34,58,36,76,52,
60, 6,46,22,30,44,68,38,14,
12,20,62,70,42,50,40,32,45,
77,37, 5,13,29,69,53,15,47,
67,35,16,56,66,26,43,59,39,
23,72,80,10, 2, 8,64,18,74
};
int main()
{
srand(time(0));
int tries = 0;
do {
init();
tries++;
addNumbers();
} while (!checkValid());
for (int i = 0; i < 81; i++)
printf("%i",selected[i]);
printf("\n");
// prettyPrint();
// printf("tried: %i times\n", tries);
// printf("%s\n", checkValid()?"valid":"invalid");
for (int i = 0; i < 81; i++) {
int j = removeZigZag[i] - 1;
if (canRemoveCell(j)) {
selected[j] = 0;
// prettyPrint();
}
}
for (int i = 0; i < 81; i++)
printf("%i",selected[i]);
printf("\n");
return 0;
}