第19講 座標の工夫による魔方陣自動生成ソフトの高速化
第6話 コード解説その1
if(s==n-1 && t==n-1){
w=0;
for(j=0;j<n;j++)w=w+x[j][j];
if(w!=n*(n*n+1)/2)goto tobi;
}
if(s==n-1 && t==0){
w=0;
for(j=0;j<n;j++)w=w+x[j][n-1-j];
if(w!=n*(n*n+1)/2)goto tobi;
}
if(s==0 && t==n-2){
w=0;
for(j=0;j<n;j++)w+=x[s][j];
if(w!=n*(n*n+1)/2)goto tobi;
}
if(s==n-2 && t==0){
w=0;
for(j=0;j<n;j++)w+=x[j][t];
if(w!=n*(n*n+1)/2)goto tobi;
}
if(s>0 && s<n-1 && t==n-1){
w=0;
for(j=0;j<n;j++)w+=x[s][j];
if(w!=n*(n*n+1)/2)goto tobi;
}
if(s==n-1 && t>0 && t<n-1){
w=0;
for(j=0;j<n;j++)w+=x[j][t];
if(w!=n*(n*n+1)/2)goto tobi;
}
の解説
if(s==n-1 && t==n-1){
w=0;
for(j=0;j<n;j++)w=w+x[j][j];
if(w!=n*(n*n+1)/2)goto tobi;
}
を先頭に持ってきた理由は、番号付け替えによって
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
0 | 1 | 2 | 3 | 4 | |
0 | 0 | 9 | 10 | 11 | 5 |
1 | 12 | 1 | 13 | 6 | 14 |
2 | 15 | 16 | 2 | 17 | 18 |
3 | 19 | 7 | 20 | 3 | 21 |
4 | 8 | 22 | 23 | 24 | 4 |
一番最初に対象となるすべてのセルに数字が埋まるからです。
n=4のときすなわち4次魔方陣のとき、n-1は3ですから、
s==n-1 && t==n-1はs==3 && t==3
となり、
3 |
のセルを示していることが分かります。
同様に、 n=5のときすなわち5次魔方陣のとき、n-1は4ですから、
s==n-1 && t==n-1はs==4 && t==4
となり、
4 |
のセルを示していることが分かります。
ですから、対角線のセルに数字がすべて埋まっていますよね。
なので、
w=0;
for(j=0;j<n;j++)w=w+x[j][j];
if(w!=n*(n*n+1)/2)goto tobi;
によって、対角線の合計がn*(n*n+1)/2になるかどうかを検査しているわけです。
n=4のときは、n*(n*n+1)/2=4×(4×4+1)/2=34
ですし、
n=5のときは、n*(n*n+1)/2=5×(5×5+1)/2=65
で、それぞれ4次魔方陣と5次魔方陣の行・列・行の合計です。
if(s==n-1 && t==0){
w=0;
for(j=0;j<n;j++)w=w+x[j][n-1-j];
if(w!=n*(n*n+1)/2)goto tobi;
}
が2番目に来る理由はお分かりですね。
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
0 | 1 | 2 | 3 | 4 | |
0 | 0 | 9 | 10 | 11 | 5 |
1 | 12 | 1 | 13 | 6 | 14 |
2 | 15 | 16 | 2 | 17 | 18 |
3 | 19 | 7 | 20 | 3 | 21 |
4 | 8 | 22 | 23 | 24 | 4 |
n=4のときすなわち4次魔方陣のとき、n-1は3ですから、
s==n-1 && t==0はs==3 && t==0
となり、
7 |
のセルの場合になります。
同様に、 n=5のときすなわち5次魔方陣のとき、n-1は4ですから、
s==n-1 && t==0はs==4 && t==0
となり、
8 |
のセルの場合になり、
逆対角線のすべてのセルが埋まっていることになります。
次の
if(s==0 && t==n-2){
w=0;
for(j=0;j<n;j++)w+=x[s][j];
if(w!=n*(n*n+1)/2)goto tobi;
}
はどういう意味でしょうか。
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
0 | 1 | 2 | 3 | 4 | |
0 | 0 | 9 | 10 | 11 | 5 |
1 | 12 | 1 | 13 | 6 | 14 |
2 | 15 | 16 | 2 | 17 | 18 |
3 | 19 | 7 | 20 | 3 | 21 |
4 | 8 | 22 | 23 | 24 | 4 |
4次魔方陣では9のセル、5次魔方陣では11のセルに数字が埋まったときに、
1行目のすべてのセルに数字が埋まったことになります。
それぞれのセル(青のセル)はx[0][n-2]に対応しています。
n=4のときすなわち4次魔方陣のとき、n-2は2ですから、
s==0 && t==n-2はs==0 && t==2
となり、
9 |
のセルになりますし、
n=5のときすなわち5次魔方陣のとき、n-2は3ですから、
s==0 && t==n-2はs==0 && t==3
となり、
11 |
のセルに対応してますよね。
ですから、4次魔方陣の場合も5次魔方陣の場合も
1行目のセルが全部埋まったことになるので、
w=0;
for(j=0;j<n;j++)w+=x[s][j];
if(w!=n*(n*n+1)/2)goto tobi;
によって、行合計がn*(n*n+1)/2になっているかどうかを確認しているわけす。
少し長くなりましたので、続きは次話で解説します。