第27講 数独(ナンプレ)自動生成
第9話 新しい番号付けとそれに対応する座標を設定するプログラムの解説その1
プログラム主要部分再掲
・・・
void zh(int n,int *p,int *q){
int i,j,k,l,cn,a[9][9];
for(i=0;i<3;i++){
for(j=0;j<3;j++){
for(k=0;k<3;k++){
for(l=0;l<3;l++){
a[3*i+k][3*j+l]=9*(3*i+j)+3*k+l;
}
}
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
p[a[i][j]]=j;
q[a[i][j]]=i;
}
}
}
・・・・
void h(int m[10][10],int n){
int i,j;
for(i=0;i<n+1;i++){
if(i%3==0){
for(j=0;j<n+4;j++){
if(j<n+3 && j%4!=0)cout<<" **";
if(j%4==0)cout<<" *";
}
cout<<endl;
if(i==n)break;
}
for(j=0;j<n+1;j++){
//if(m[i][j]<10)cout<<"0"<<m[i][j]<<"
";
if(j==0)cout<<" * ";
if(j>0 && j%3==0)cout<<"* ";
if(j<n){
if(m[i][j]<10)cout<<"0"<<m[i][j]<<"
";
if(m[i][j]>=10)cout<<m[i][j]<<" ";
}
}
cout<<endl;
}
}
解説
解説しなければならないことは2つです。
void zh(int n,int *p,int *q)とvoid h(int m[10][10],int n)についてです。
まず、void zh(int n,int *p,int *q)から説明しましょう。
int i,j,k,l,cn,a[9][9];
において、2次元配列a[9][9]を用意する意味は、
優秀な皆さんならお分かりですね。
座標を設定する前に、
新しい番号付け
をするためですね。
void zh(int n,int *p,int *q)の任務は、
座標を設定することですが、
設定する前には数字を入れる順番gを先に、
決めておかないと出来ません。
元々は
void zh(int n,int *p,int *q){
int i,j,cn;
int a[10][10];
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i][j]=-1;
for(i=0;i<n;i++)a[i][i]=i;
cn=n;
for(i=0;i<n;i++){
if(a[i][n-1-i]==-1){
a[i][n-1-i]=cn;
cn++;
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i][j]==-1){
a[i][j]=cn;
cn++;
}
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
p[a[i][j]]=j;
q[a[i][j]]=i;
}
}
}
となっていたことを思い出せば、
a[9][9]を用意する意味は明らかです。
問題は、
for(i=0;i<3;i++){
for(j=0;j<3;j++){
for(k=0;k<3;k++){
for(l=0;l<3;l++){
a[3*i+k][3*j+l]=9*(3*i+j)+3*k+l;
}
}
}
}
4次元for文です。
2次元for文でさえ、頭が混乱するのに4次元です。
ヒントに、
for(i=0;i<3;i++){
for(j=0;j<3;j++){
for(k=0;k<3;k++){
for(l=0;l<3;l++){
a[3*i+k][3*j+l]=9*(3*i+k)+3*j+l;
}
}
}
}
としたのでは、
for(i=0;i<3;i++){
for(j=0;j<3;j++){
a[i][j]=9*i+j;
}
}
と書いたことを思い出して下さい。
この番号付けでは、
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
となってしまいますね。
どうして、
for(i=0;i<3;i++){
for(j=0;j<3;j++){
for(k=0;k<3;k++){
for(l=0;l<3;l++){
a[3*i+k][3*j+l]=9*(3*i+k)+3*j+l;
}
}
}
}
と
for(i=0;i<3;i++){
for(j=0;j<3;j++){
a[i][j]=9*i+j;
}
}
は同じなのでしょうか。
これが分かれば、
for(i=0;i<3;i++){
for(j=0;j<3;j++){
for(k=0;k<3;k++){
for(l=0;l<3;l++){
a[3*i+k][3*j+l]=9*(3*i+j)+3*k+l;
}
}
}
}
によって、
0 | 1 | 2 | 9 | 10 | 11 | 18 | 19 | 20 |
3 | 4 | 5 | 12 | 13 | 14 | 21 | 22 | 23 |
6 | 7 | 8 | 15 | 16 | 17 | 24 | 25 | 26 |
27 | 28 | 29 | 36 | 37 | 38 | 45 | 46 |
47 |
30 | 31 | 32 | 39 | 40 | 41 | 48 | 49 | 50 |
33 | 34 | 35 | 42 | 43 | 44 | 51 | 52 | 53 |
54 | 55 | 56 | 63 | 64 | 65 | 72 | 73 | 74 |
57 | 58 | 59 | 66 | 67 | 68 | 75 | 76 | 77 |
60 | 61 | 62 | 69 | 70 | 71 | 78 | 79 | 80 |
が実現できることを理解できます。
それぞれの場合の動きを次話でトレースしてみましょう。