You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define range9(x) for(int x = 0; x < 9; x ++)
struct Sudoku{
int inc[9][9];
};
#define MAXSIZE 1000
struct Sudoku *M_PtrReg[MAXSIZE];
int PRtp = 0;
void ptrInit(){
for(int i = 0; i < MAXSIZE; i ++)
M_PtrReg[i] = (struct Sudoku *)malloc(sizeof(struct Sudoku));
}
void ptrClear(){
for(int i = 0; i < MAXSIZE; i ++)
free(M_PtrReg[i]);
}
struct Sudoku *ptrReg(){return M_PtrReg[PRtp++];}
void ptrFree(){--PRtp;}
void sudokuClear(struct Sudoku *a){
range9(i)
range9(j)
a->inc[i][j] = 0;
}
void sudokuCopy(struct Sudoku src, struct Sudoku *dst){
range9(i)
range9(j)
dst->inc[i][j] = src.inc[i][j];
}
void sudokufromArray(int src[9][9], struct Sudoku *dst){
range9(i)
range9(j)
dst->inc[i][j] = src[i][j];
}
void sudokuPrint(struct Sudoku a){
range9(i){
if(!(i % 3)) putchar('\n');
range9(j){
if(!(j % 3)) putchar(' ');
if(!a.inc[i][j])
putchar('.');
else
// putchar(a.inc[i][j] + 48);
printf("%d", a.inc[i][j]);
putchar(' ');
}
putchar('\n');
}
}
void initRandomSeed(){srand(time(NULL));}
struct Sudoku sudokuRandomGenerate(unsigned int fill){// %
fill %= 101;
struct Sudoku *res = ptrReg();
range9(i)
range9(j)
if(rand()%100 <= fill)
res->inc[i][j] = rand() % 9 + 1;
else
res->inc[i][j] = 0;
return *res;
}
struct Sudoku tags;
int tag(struct Sudoku *a, int i, int j, int x, int y, struct Sudoku *tags){
if(i == x && j == y) return 0;
if(a->inc[i][j] == a->inc[x][y]){
printf("False:repetition found in (%d,%d) and (%d,%d) with the number {%d}\n", i+1, j+1, x+1, y+1, a->inc[x][y]);
return 1;
}
tags->inc[x][y] |= (1 << a->inc[i][j]);
return 0;
}
int tagPoint(struct Sudoku *a, int i, int j, struct Sudoku *tags){
range9(k)
if(tag(a, i, j, i, k, tags)||tag(a, i, j, k, j, tags)||tag(a, i, j, i/3*3+k/3, j/3*3+k%3, tags))
return 1;
return 0;
}
int tagsInit(struct Sudoku *a, struct Sudoku *tags){
range9(i)
range9(j)
tags->inc[i][j] |= (1 << a->inc[i][j]);
range9(i)
range9(j)
if(a->inc[i][j] && tagPoint(a, i, j, tags))
return 1;
}
int sudokuJudge(struct Sudoku a){
struct Sudoku tags;
sudokuClear(&tags);
if(tagsInit(&a, &tags)) return 1;
printf("True:Valid initial Sudoku matrix!\n");
return 0;
}
void tagFindLeast(struct Sudoku *a, int *x, int *y, struct Sudoku *tags){
int minv = 10;
int mini=0, minj=0;
range9(i)
range9(j)
if(!a->inc[i][j]){
int cnt = 0;
range9(k)
cnt += (tags->inc[i][j] >> k) & 1;
if(cnt < minv && cnt != 0){
minv = cnt;
mini = i;
minj = j;
}
}
*x = mini;
*y = minj;
}
struct Sudoku *sudokuFill__(struct Sudoku *a, int unfillednum, struct Sudoku *tags){
struct Sudoku *pres, *t_tags;
if(!unfillednum){
pres = ptrReg();
sudokuCopy(*a, pres);
sudokuPrint(*tags);
return pres;
}
int m=0, n=0;
tagFindLeast(a, &m, &n, tags);
range9(i)
if(!((tags->inc[m][n] >> i) & 1)){
a->inc[m][n] = i;
t_tags = ptrReg();
sudokuCopy(*tags, t_tags);
tagPoint(a, m, n, t_tags);
// sudokuPrint(*a);
// getchar();
pres = sudokuFill__(a, unfillednum - 1, t_tags);
if(pres)
return pres;
a->inc[m][n] = 0;
ptrFree();
}
return NULL;
}
struct Sudoku *sudokuFill(struct Sudoku *a){
struct Sudoku tags, res, *pres;
sudokuClear(&tags);
if(tagsInit(a, &tags)) return NULL;
int unfillednum = 0;
range9(i)
range9(j)
if(!a->inc[i][j])
unfillednum ++;
printf("%d", unfillednum);
return sudokuFill__(a, unfillednum, &tags);
}
int main(){
ptrInit();
initRandomSeed();
struct Sudoku a;
sudokuCopy(sudokuRandomGenerate(10), &a);
printf("The original Sudoku matrix: \n");
sudokuPrint(a);
if(sudokuJudge(a)){
printf("No solution\n");
ptrClear();
return 0;
}
struct Sudoku *pres = sudokuFill(&a);
if(!pres){
printf("No solution\n");
ptrClear();
return 0;
}
printf("The solution of Sudoku matrix:\n");
sudokuPrint(*pres);
printf("%d", PRtp);
ptrClear();
}