|
View previous topic :: View next topic |
Author |
Message |
| dukuso
| Joined: 14 Jul 2005 | Posts: 424 | : | Location: germany | Items |
|
Posted: Sat Sep 03, 2005 8:23 pm Post subject: short and fast sudoku-generator in C |
|
|
Code: |
/* short and fast sudoku-generator in C, compiled with gcc3.2
executable at http://magictour.free.fr/suexg.exe
repost bugs,improvement-suggestions to sterten@aol.com
for some explanation of the solver
http://magictour.free.fr/suexco.txt
generates about 13 almost random sudokus per second with 1 GHz
by starting from an empty grid,
starting from a full grid is about 4 times faster
the generated sudokus are locally minimal, so removing
any clue results in a puzzle with multiple solutions
this program is public domain
*/
#include <stdio.h>
#define MWC ( (zr=36969*(zr&65535)+(zr>>16)) ^ (wr=18000*(wr&65535)+(wr>>16)) )
unsigned zr=362436069, wr=521288629;
int Rows[325],Cols[730],Row[325][10],Col[730][5],Ur[730],Uc[325],V[325];
int P[88],A[88],C[88],I[88];
int s1,m0,c1,c2,r1,l,i1,m1,m2,a,p,i,j,k,r,c,d,n=729,m=324,x,y,s;
int seed,solutions,min,clues,match;
char L[11]=".123456789";
int solve();
int main(int argc,char*argv[]){
if(argc<2){printf("\nusage:suexg seed\n\n generates locally minimal sudokus\n");exit(1);}
sscanf(argv[1],"%i",&seed);zr^=seed;wr+=seed;
r=0;for(x=1;x<=9;x++)for(y=1;y<=9;y++)for(s=1;s<=9;s++){
r++;Cols[r]=4;Col[r][1]=x*9-9+y;Col[r][2]=(3*((x-1)/3)+(y-1)/3)*9+s+81;
Col[r][3]=x*9-9+s+81*2;Col[r][4]=y*9-9+s+81*3;}
for(c=1;c<=m;c++)Rows[c]=0;
for(r=1;r<=n;r++)for(c=1;c<=Cols[r];c++){
a=Col[r][c];Rows[a]++;Row[a][Rows[a]]=r;}
m0: for(i=1;i<=81;i++)A[i]=0;
mr1:i1=(MWC>>8)&127;if(i1>80)goto mr1;i1++;if(A[i1])goto mr1;
mr3:s=(MWC>>9)&15;if(s>8)goto mr3;s++;
A[i1]=s;m2=solve();
if(m2<1)A[i1]=0;if(m2!=1)goto mr1;
for(i=1;i<=81;i++){mr4:x=(MWC>>8)&127;if(x>=i)goto mr4;x++;P[i]=P[x];P[x]=i;}
for(i1=1;i1<=81;i1++){s1=A[P[i1]];A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
for(i=1;i<=81;i++)printf("%c",L[A[i]]);printf("\n");
goto m0;
return 0;}
int solve(){
for(i=0;i<=n;i++)Ur[i]=0;for(i=0;i<=m;i++)Uc[i]=0;
clues=0;for(i=1;i<=81;i++)
if(A[i]){clues++;r=i*9-9+A[i];
for(j=1;j<=Cols[r];j++){d=Col[r][j];if(Uc[d])return 0;Uc[d]++;
for(k=1;k<=Rows[d];k++){Ur[Row[d][k]]++;}}}
for(c=1;c<=m;c++){V[c]=0;for(r=1;r<=Rows[c];r++)if(Ur[Row[c][r]]==0)V[c]++;}
i=clues;m0=0;m1=0;solutions=0;
m2:i++;I[i]=0;min=n+1;if(i>81 || m0)goto m4;
if(m1){C[i]=m1;goto m3;}
for(c=1;c<=m;c++)if(!Uc[c]){if(V[c]<=min)c1=c;
if(V[c]<min){min=V[c];C[i]=c;if(min<2)goto m3;}}
m3:c=C[i];I[i]++;if(I[i]>Rows[c])goto m4;
r=Row[c][I[i]];if(Ur[r])goto m3;m0=0;m1=0;
for(j=1;j<=Cols[r];j++){c1=Col[r][j];Uc[c1]++;}
for(j=1;j<=Cols[r];j++){c1=Col[r][j];
for(k=1;k<=Rows[c1];k++){r1=Row[c1][k];Ur[r1]++;if(Ur[r1]==1)
for(l=1;l<=Cols[r1];l++){c2=Col[r1][l];V[c2]--;
if(Uc[c2]+V[c2]<1)m0=c2;if(Uc[c2]==0 && V[c2]<2)m1=c2;}}}
if(i==81)solutions++;if(solutions>1)goto m9;goto m2;
m4:i--;c=C[i];r=Row[c][I[i]];if(i==clues)goto m9;
for(j=1;j<=Cols[r];j++){c1=Col[r][j];Uc[c1]--;
for(k=1;k<=Rows[c1];k++){r1=Row[c1][k];Ur[r1]--;
if(Ur[r1]==0)for(l=1;l<=Cols[r1];l++){c2=Col[r1][l];V[c2]++;}}}
if(i>clues)goto m3;
m9:return solutions;} |
Last edited by dukuso on Mon Oct 03, 2005 2:48 pm; edited 2 times in total |
|
Back to top |
|
|
| Misza
| Joined: 14 Sep 2005 | Posts: 1 | : | | Items |
|
Posted: Wed Sep 14, 2005 7:04 pm Post subject: Nice |
|
|
Nice code. Have you considered entering the International Obfuscated C Contest? Or is that you entry into it? |
|
Back to top |
|
|
| dukuso
| Joined: 14 Jul 2005 | Posts: 424 | : | Location: germany | Items |
|
Posted: Wed Sep 14, 2005 7:18 pm Post subject: |
|
|
well, I like when it can be printed on one page.
But I'm not trying to obfuscate it.
Sorry, if you feel so.
OK, if there is demand, I'll add some comments |
|
Back to top |
|
|
| Paul
| Joined: 11 Aug 2005 | Posts: 29 | : | | Items |
|
Posted: Sun Oct 02, 2005 6:23 pm Post subject: |
|
|
Could you explain how to run your .exe?
Specifically, what is the 'seed'? The only sudoku's i have managed to generate have been unsolvable by logic so far.
Thanks! |
|
Back to top |
|
|
| dukuso
| Joined: 14 Jul 2005 | Posts: 424 | : | Location: germany | Items |
|
Posted: Sun Oct 02, 2005 7:18 pm Post subject: |
|
|
the seed initializes the random generator.
Same seed - same sudokus.
About 50% of the generated sudokus should be solvable with
naked single/hidden single alone.
Here is a new version :
Code: |
char G[9999]="
suexg version 12, small randomized sudoku-generator in C,
generates about 24 sudokus per second with 1GHz
based on an exact cover solver, compiled with gcc3.2
Report bugs,improvement suggestions,feedback to sterten@aol.com
For some explanation of the solver see: http://magictour.free.fr/suexco.txt
This generator starts from an empty grid and adds clues completely at random
There are faster pseudo-random methods which generate upto 1000 sudokus
per second.
For a solver see: http://magictour.free.fr/suexk.exe
(C-sourcecode is attached to the executable )
Send sudokus with rating more than 100000 to sterten@aol.com
so they can be included in the list of hardest sudokus at
http://magictour.free.fr/top94
You can download a DOS/Windows executable of this program from
http://magictour.free.fr/suexg.exe
This software is public domain
";
#include <stdio.h>
#define MWC ((zr=36969*(zr&65535)+(zr>>16))^(wr=18000*(wr&65535)+(wr>>16)))
unsigned zr=362436069, wr=521288629;
int Rows[325],Cols[730],Row[325][10],Col[730][5],Ur[730],Uc[325],V[325],W[325];
int P[88],A[88],C[88],I[88],Two[888];
// char B[83]="0111155555135559999135999888133947778113946678333442678344422678442226678222666778";
char B[83]="0111222333111222333111222333444555666444555666444555666777888999777888999777888999";
int w,f,s1,m0,c1,c2,r1,l,i1,m1,m2,a,p,i,j,k,r,c,d,n=729,m=324,x,y,s;
int q7,part,nt,rate,nodes,seed,solutions,min,samples,sam1,clues;
char L[11]=".123456789";
FILE *file;
int solve();
//------------------------------------------------------------
int main(int argc,char*argv[]){
if(argc<2){printf("\nusage:suexg random-seed [z] [with rating] \n\n");
printf(" generates z locally minimal sudokus [and rates them]\n");
printf(" use different numbers for seed to get different streams of sudokus\n");
printf(" default is : z=1e9 and without rating [if these are not specified]\n");
printf(" to redirect the sudokus to a file use e.g. : suexg 0 100 r >file\n");
printf("\n suexg i : printf more info\n \n");
exit(1);}
sscanf(argv[1],"%i",&seed);zr^=seed;wr+=seed;
samples=1000000000;if(argc>2)sscanf(argv[2],"%i",&samples);
rate=0;if(argc>3)rate=1;
if(argv[1][0]=='i'){printf("%s",G);exit(0);}
for(i=0;i<888;i++){j=1;while(j<=i)j+=j;Two[i]=j-1;}
r=0;for(x=1;x<=9;x++)for(y=1;y<=9;y++)for(s=1;s<=9;s++){
r++;Cols[r]=4;Col[r][1]=x*9-9+y;Col[r][2]=(B[x*9-9+y]-48)*9-9+s+81;
Col[r][3]=x*9-9+s+81*2;Col[r][4]=y*9-9+s+81*3;}
for(c=1;c<=m;c++)Rows[c]=0;
for(r=1;r<=n;r++)for(c=1;c<=Cols[r];c++){
a=Col[r][c];Rows[a]++;Row[a][Rows[a]]=r;}
sam1=0;
m0s:sam1++;if(sam1>samples)exit(0);
m0: for(i=1;i<=81;i++)A[i]=0;part=0;q7=0;
mr1:i1=(MWC>>8)&127;if(i1>80)goto mr1;i1++;if(A[i1])goto mr1;
mr3:s=(MWC>>9)&15;if(s>8)goto mr3;s++;
A[i1]=s;m2=solve();q7++;//if(q7>999)goto m0;
// add a random clue and solve it. No solution ==> remove it again.
// Not yet a unique solution ==> continue adding clues
if(m2<1)A[i1]=0;if(m2!=1)goto mr1;
//now we have a unique-solution sudoku. Now remove clues to make it minimal
part++;if(solve()!=1)goto m0;
for(i=1;i<=81;i++){mr4:x=(MWC>>8)&127;if(x>=i)goto mr4;x++;P[i]=P[x];P[x]=i;}
for(i1=1;i1<=81;i1++){s1=A[P[i1]];A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
if(rate){nt=0;for(f=0;f<100;f++){solve();nt+=nodes;}printf("rating:%6i , ",nt);}
for(i=1;i<=81;i++)printf("%c",L[A[i]]);printf("\n");
goto m0s;}
//-----------------------------------------------------------------------
int solve(){//returns 0 (no solution), 1 (unique sol.), 2 (more than one sol.)
for(i=0;i<=n;i++)Ur[i]=0;for(i=0;i<=m;i++)Uc[i]=0;
clues=0;for(i=1;i<=81;i++)
if(A[i]){clues++;r=i*9-9+A[i];
for(j=1;j<=Cols[r];j++){d=Col[r][j];if(Uc[d])return 0;Uc[d]++;
for(k=1;k<=Rows[d];k++){Ur[Row[d][k]]++;}}}
for(c=1;c<=m;c++){V[c]=0;for(r=1;r<=Rows[c];r++)if(Ur[Row[c][r]]==0)V[c]++;}
i=clues;m0=0;m1=0;solutions=0;nodes=0;
m2:i++;I[i]=0;min=n+1;if(i>81 || m0)goto m4;
if(m1){C[i]=m1;goto m3;}
w=0;for(c=1;c<=m;c++)if(!Uc[c]) { if(V[c]<2){C[i]=c;goto m3;}
if(V[c]<=min){w++;W[w]=c;};
if(V[c]<min){w=1;W[w]=c;min=V[c];} }
mr:c2=MWC&Two[w];if(c2>=w)goto mr;C[i]=W[c2+1];
m3:c=C[i];I[i]++;if(I[i]>Rows[c])goto m4;
r=Row[c][I[i]];if(Ur[r])goto m3;m0=0;m1=0;
nodes++;//if(nodes>9999 && part==0)return 0;
for(j=1;j<=Cols[r];j++){c1=Col[r][j];Uc[c1]++;}
for(j=1;j<=Cols[r];j++){c1=Col[r][j];
for(k=1;k<=Rows[c1];k++){r1=Row[c1][k];Ur[r1]++;if(Ur[r1]==1)
for(l=1;l<=Cols[r1];l++){c2=Col[r1][l];V[c2]--;
if(Uc[c2]+V[c2]<1)m0=c2;if(Uc[c2]==0 && V[c2]<2)m1=c2;}}}
if(i==81)solutions++;if(solutions>1)goto m9;goto m2;
m4:i--;c=C[i];r=Row[c][I[i]];if(i==clues)goto m9;
for(j=1;j<=Cols[r];j++){c1=Col[r][j];Uc[c1]--;
for(k=1;k<=Rows[c1];k++){r1=Row[c1][k];Ur[r1]--;
if(Ur[r1]==0)for(l=1;l<=Cols[r1];l++){c2=Col[r1][l];V[c2]++;}}}
if(i>clues)goto m3;
m9:return solutions;}
|
|
|
Back to top |
|
|
| Paul
| Joined: 11 Aug 2005 | Posts: 29 | : | | Items |
|
Posted: Wed Oct 19, 2005 2:55 pm Post subject: |
|
|
Thanks, have now got this working.
Very fast, and i like the fact it can output to a file. The only improvement i can see would be to add symmetry (but that's just a personal preference).
Cheers,
Paul |
|
Back to top |
|
|
| fmr
| Joined: 13 Dec 2005 | Posts: 1 | : | | Items |
|
Posted: Tue Dec 13, 2005 3:42 pm Post subject: |
|
|
In this piece of code:
dukuso wrote: | for(i1=1;i1<=81;i1++){s1=A[P[i1]];A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
|
I changed it to:
Code: | for(i1=1;i1<=81;i1++){s1=A[P[i1]];if( !s1 ) continue; A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
|
This avoids solving a grid where you replace a 0 (no clue) by another 0. I gained about 40% increase in speed. Is there anything wrong by doing this ? I know the solver uses the random generator (MWC) to solve the grids, so by doing this I'm likely to change the resulting grids. |
|
Back to top |
|
|
| dukuso
| Joined: 14 Jul 2005 | Posts: 424 | : | Location: germany | Items |
|
Posted: Wed Dec 14, 2005 12:48 am Post subject: |
|
|
fmr wrote: | In this piece of code:
dukuso wrote: | for(i1=1;i1<=81;i1++){s1=A[P[i1]];A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
|
I changed it to:
Code: | for(i1=1;i1<=81;i1++){s1=A[P[i1]];if( !s1 ) continue; A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
|
This avoids solving a grid where you replace a 0 (no clue) by another 0. I gained about 40% increase in speed. Is there anything wrong by doing this ? I know the solver uses the random generator (MWC) to solve the grids, so by doing this I'm likely to change the resulting grids. |
that's OK. In other versions I do this checking too.
Speed was not so much an issue here.
It was in the 16*16 version, which should be somewhere here too.
Bo had optimized it |
|
Back to top |
|
|
| King Wonka
| Joined: 14 Dec 2005 | Posts: 26 | : | | Items |
|
Posted: Thu Dec 15, 2005 2:01 pm Post subject: |
|
|
hi dukuso,
Can you tell me what MWC is used for? Is it part of generating random numbers? I do the math manually and I get MWC=1.
Also, what does bitwise shift right on MWC and 8 & 127 do?
Code: | #define MWC ((zr=36969*(zr&65535)+(zr>>16))^(wr=18000*(wr&65535)+(wr>>16)))
i1=(MWC>>8)&127 |
|
|
Back to top |
|
|
| King Wonka
| Joined: 14 Dec 2005 | Posts: 26 | : | | Items |
|
Posted: Thu Dec 15, 2005 8:50 pm Post subject: |
|
|
Quote: | I know the solver uses the random generator (MWC) to solve the grids, so by doing this I'm likely to change the resulting grids. |
Ok...I see that MWC *is* the random generator.
On that note what are the constraints of i1=(MWC>>8)&127?
Between what 2 numbers will the random number fall?
KW |
|
Back to top |
|
|
| dukuso
| Joined: 14 Jul 2005 | Posts: 424 | : | Location: germany | Items |
|
Posted: Fri Dec 16, 2005 5:50 pm Post subject: |
|
|
King Wonka wrote: | Quote: | I know the solver uses the random generator (MWC) to solve the grids, so by doing this I'm likely to change the resulting grids. |
Ok...I see that MWC *is* the random generator. :oops:
On that note what are the constraints of i1=(MWC>>8)&127?
Between what 2 numbers will the random number fall?
KW |
0 and 127.
The ">>8" is maybe not necessary. Just to make it more random.
You can replace MWC with another random number generator |
|
Back to top |
|
|
| King Wonka
| Joined: 14 Dec 2005 | Posts: 26 | : | | Items |
|
Posted: Sat Dec 17, 2005 2:08 am Post subject: |
|
|
dukuso,
I'm still studying this code and I've found why it's not compiling for me. This line:
Code: | Col[r][2]=(B[x*9-9+y]-48)*9-9+s+81 |
It appears you're subtracting 48 from a string. That's where my error is coming from. Is there a substitue I can use instead that doesn't do that? |
|
Back to top |
|
|
| angusj Site Admin
| Joined: 18 Jun 2005 | Posts: 406 | : | | Items |
|
Posted: Sat Dec 17, 2005 5:35 am Post subject: |
|
|
King Wonka wrote: | It appears you're subtracting 48 from a string. That's where my error is coming from. |
You're evidently using a good compiler - one which type checks variables. Anyhow, you can safely cast the offending char to an int here as dukuso appears to be using the ordinal value of that char. |
|
Back to top |
|
|
| King Wonka
| Joined: 14 Dec 2005 | Posts: 26 | : | | Items |
|
Posted: Sat Dec 17, 2005 6:23 am Post subject: |
|
|
Ok I converted the:
to an integer and how I'm getting a negative answer and an out of arrary error. Answer was like -359 if memory serves. I plugged in the old formula from the first version in this thread and it seems to be working. Still would like to figure out the ordinal thing though.
Anthony |
|
Back to top |
|
|
| dukuso
| Joined: 14 Jul 2005 | Posts: 424 | : | Location: germany | Items |
|
Posted: Sat Dec 17, 2005 7:00 am Post subject: |
|
|
hi Anthony,
what compiler are you using ? I use gcc3.2 and there are no problems.
Others compiled it as well.
The B[] array is not meant as a string but as an array of integers.
It's just easier to enter them as a string.
You could replace the line :
char B[83]="011....
by:
int B[83]={48,49,49,...
just the ASCII-codes.
below is a more recent version:
Code: |
//option to generate several sudokus starting from the same random grid
//head-message as C-comment, printing it as with 's'-option
char G[9999]="
suexg version 16, Oct.29.2005
randomized,public-domain sudoku-generator with C-sourcecode,
generates about 24 sudokus per second with 1GHz
based on an exact cover solver, compiled with gcc3.2
Report bugs,improvement suggestions,feedback to sterten@aol.com
For some explanation of the solver see: http://magictour.free.fr/suexco.txt
This generator starts from an empty grid and adds clues completely at random
There are faster pseudo-random methods which generate upto 1000 sudokus
per second.
For a solver see: http://magictour.free.fr/suexk.exe
(C-sourcecode is attached to the executable )
Send feedback to sterten@aol.com
You can download a DOS/Windows executable of this program from
http://magictour.free.fr/suexg.exe
This software is public domain
";
#include <stdio.h>
#define MWC ((zr=36969*(zr&65535)+(zr>>16))^(wr=18000*(wr&65535)+(wr>>16)))
unsigned zr=362436069, wr=521288629;
int Rows[325],Cols[730],Row[325][10],Col[730][5],Ur[730],Uc[325],V[325],W[325];
int P[88],A[88],A0[88],C[88],I[88],Two[888];
// char B[83]="0111155555135559999135999888133947778113946678333442678344422678442226678222666778";
char B[83]="0111222333111222333111222333444555666444555666444555666777888999777888999777888999";
char H[326][7];
int b,w,f,s1,m0,c1,c2,r1,l,i1,m1,m2,a,p,i,j,k,r,c,d,n=729,m=324,x,y,s;
int mi1,mi2,q7,part,nt,rate,nodes,seed,solutions,min,samples,sam1,clues;
char L[99]=".123456789";
FILE *file;
int solve();
//------------------------------------------------------------
int main(int argc,char*argv[]){
if(argc<2){printf("\nusage:suexg random-seed [z] [file] [with rating] \n\n");
printf(" generates z locally minimal sudokus [and rates them]\n");
printf(" use different numbers for seed to get different streams of sudokus\n");
printf(" default is : z=1e9 and without rating [if these are not specified]\n");
printf(" if file is given then for each puzzle in file z random sudokus are given\n");
printf(" by starting from the given puzzle rather than from an empty grid\n");
printf(" to redirect the sudokus to a file use e.g. : suexg 0 100 r >file\n");
printf("\n suexg i : printf more info\n suexg s : prints source-code\n");
exit(1);}
sscanf(argv[1],"%i",&seed);zr^=seed;wr+=seed;
samples=1000000000;if(argc>2)sscanf(argv[2],"%i",&samples);
rate=0;if(argc>3)rate=1;if(argc>4)rate=2;
if(argv[1][0]=='i'){printf("%s",G);exit(0);}
if(argv[1][0]=='s'){if((file=fopen(argv[0],"rb"))==NULL)
{printf("\ncan't find suexg.exe\n");exit(1);}
ip1:w=0;for(i=1;i<33;i++)w+=(fgetc(file)==45);if(w<32)goto ip1;
while(fgetc(file)!='_');
ip2:x=fgetc(file);if(x!=13)printf("%c",x);if(feof(file))exit(1);goto ip2;}
if(argv[3][0]>'9')rate=0;
if(argv[3][0]>'9')if((file=fopen(argv[3],"rb"))==NULL)
{printf("\ncan't find file %s\n",argv[3]);exit(1);}
for(i=0;i<888;i++){j=1;while(j<=i)j+=j;Two[i]=j-1;}
for(i=1;i<=81;i++)A0[i]=0;
r=0;for(x=1;x<=9;x++)for(y=1;y<=9;y++)for(s=1;s<=9;s++){
r++;Cols[r]=4;Col[r][1]=x*9-9+y;Col[r][2]=(B[x*9-9+y]-48)*9-9+s+81;
Col[r][3]=x*9-9+s+81*2;Col[r][4]=y*9-9+s+81*3;}
for(c=1;c<=m;c++)Rows[c]=0;
for(r=1;r<=n;r++)for(c=1;c<=Cols[r];c++){
a=Col[r][c];Rows[a]++;Row[a][Rows[a]]=r;}
c=0;for(x=1;x<=9;x++)for(y=1;y<=9;y++){c++;H[c][0]='r';H[c][1]=x+48;H[c][2]='c';H[c][3]=y+48;H[c][4]=0;}
c=81;for(b=1;b<=9;b++)for(s=1;s<=9;s++){c++;H[c][0]='b';H[c][1]=b+48;H[c][2]='s';H[c][3]=s+48;H[c][4]=0;}
c=81*2;for(x=1;x<=9;x++)for(s=1;s<=9;s++){c++;H[c][0]='r';H[c][1]=x+48;H[c][2]='s';H[c][3]=s+48;H[c][4]=0;}
c=81*3;for(y=1;y<=9;y++)for(s=1;s<=9;s++){c++;H[c][0]='c';H[c][1]=y+48;H[c][2]='s';H[c][3]=s+48;H[c][4]=0;}
m6:if(argv[3][0]>'9')
for(i=1;i<=81;i++){
m6a:A0[i]=fgetc(file)-48;if(feof(file))exit(8);
if(A0[i]==-2)A0[i]=0;if(A0[i]<0 || A0[i]>9)goto m6a;}
sam1=0;
m0s:sam1++;if(sam1>samples){if(argv[3][0]<'9')exit(8);goto m6;}
// printf("%i %i\n",sam1,samples);
m0:for(i=1;i<=81;i++)A[i]=A0[i];part=0;solve();
//now we have a unique-solution sudoku. Now remove clues to make it minimal
part++;
for(i=1;i<=81;i++){mr4:x=(MWC>>8)&127;if(x>=i)goto mr4;x++;P[i]=P[x];P[x]=i;}
for(i1=1;i1<=81;i1++){s1=A[P[i1]];A[P[i1]]=0;if(solve()>1)A[P[i1]]=s1;}
if(rate){nt=0;mi1=9999;for(f=0;f<100;f++){solve();nt+=nodes;if(nodes<mi1)
{mi1=nodes;mi2=C[clues];}}
printf("rating:%6i , ",nt);if(rate>1)printf("hint:%s ",H[mi2]);}
for(i=1;i<=81;i++)printf("%c",L[A[i]]);printf("\n");
goto m0s;}
//-----------------------------------------------------------------------
int solve(){//returns 0 (no solution), 1 (unique sol.), 2 (more than one sol.)
for(i=0;i<=n;i++)Ur[i]=0;for(i=0;i<=m;i++)Uc[i]=0;
clues=0;for(i=1;i<=81;i++)
if(A[i]){clues++;r=i*9-9+A[i];
for(j=1;j<=Cols[r];j++){d=Col[r][j];if(Uc[d])return -1;Uc[d]++;
for(k=1;k<=Rows[d];k++){Ur[Row[d][k]]++;}}}
for(c=1;c<=m;c++){V[c]=0;for(r=1;r<=Rows[c];r++)if(Ur[Row[c][r]]==0)V[c]++;}
i=clues;m0=0;m1=0;solutions=0;
m2:i++;I[i]=0;min=n+1;if(i>81 || m0)goto m4;
if(m1){C[i]=m1;goto m3;}
w=0;for(c=1;c<=m;c++)if(!Uc[c]) { if(V[c]<2){C[i]=c;goto m3;}
if(V[c]<=min){w++;W[w]=c;};
if(V[c]<min){w=1;W[w]=c;min=V[c];} }
mr:c2=MWC&Two[w];if(c2>=w)goto mr;C[i]=W[c2+1];
m3:c=C[i];I[i]++;if(I[i]>Rows[c])goto m4;
r=Row[c][I[i]];if(Ur[r])goto m3;m0=0;m1=0;
if(part==0){j=9;k=81;x=(r-1)/k+1;y=((r-1)%k)/j+1;s=(r-1)%j+1;A[x*9-9+y]=s;P[x*9-9+y]=i;}
for(j=1;j<=Cols[r];j++){c1=Col[r][j];Uc[c1]++;}
for(j=1;j<=Cols[r];j++){c1=Col[r][j];
for(k=1;k<=Rows[c1];k++){r1=Row[c1][k];Ur[r1]++;if(Ur[r1]==1)
for(l=1;l<=Cols[r1];l++){c2=Col[r1][l];V[c2]--;
if(Uc[c2]+V[c2]<1)m0=c2;if(Uc[c2]==0 && V[c2]<2)m1=c2;}}}
if(i==81){solutions++;if(solutions>1)return 2;if(part==0)return 1;}
goto m2;
m4:i--;c=C[i];r=Row[c][I[i]];if(i==clues)goto m9;
for(j=1;j<=Cols[r];j++){c1=Col[r][j];Uc[c1]--;
for(k=1;k<=Rows[c1];k++){r1=Row[c1][k];Ur[r1]--;
if(Ur[r1]==0)for(l=1;l<=Cols[r1];l++){c2=Col[r1][l];V[c2]++;}}}
if(i>clues)goto m3;
m9:return solutions;}
|
Last edited by dukuso on Wed Dec 21, 2005 11:23 am; edited 1 time in total |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
Igloo Theme Version 1.0 :: Created By: Andrew Charron
|