第19講 座標の工夫による魔方陣自動生成ソフトの高速化
第8話 各セルに入れる数字の始まりを変える
コード主要部分再掲
long f(int **x,int n,long cn,int g){
int i,j,s,t,w,v;
s=g/n;
t=g%n;
for(i=1;i<n*n+1;i++){
x[s][t]=i;
v=0;
if(k[i-1]==0){
k[i-1]=1;
v=1;
}
else{
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;
}
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;
}
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(g+1<n*n){
cn=f(x,n,cn,g+1);
if(cn==100)return(cn);
}
else{
h(x,n);
cn++;
if(cn==100)return(cn);
}
tobi:;
if(cn==100)return(cn);
if(v==1)k[i-1]=0;
}
return(cn);
}
このプログラムでは、各セルに
4次魔方陣の場合
1,2,3,4,・・・・,15,16
5次魔方陣場合
1,2,3,4,・・・・,24,25
と順番に入れています。
ですから、セルは
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | * | * | * |
2 | * | * | * | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | * | * | * | * |
2 | * | * | * | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 1 | * | * |
2 | * | * | * | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | 1 | * | * | * |
2 | * | * | * | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | * | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | 2 | * | * | * |
2 | * | * | * | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | 1 | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | 2 | * | * | * |
2 | * | * | 1 | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | 2 | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | 2 | * | * | * |
2 | * | * | 2 | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | 3 | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | 2 | * | * | * |
2 | * | * | 3 | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
のように動いていきます。
4次魔方陣の場合は、すでに破綻しています。
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | 3 | * |
3 | * | * | * | * |
最後のセルに最大の25入れても、
合計を34にすることは出来ません。
それで1つ前の段階の修正を余儀なくされ、
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | 24 | * |
3 | * | * | * | * |
までいって、次ぎに
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 2 | * | * |
2 | * | * | 24 | * |
3 | * | * | * | 25 |
最初の対角線が完成します。
もし順番に入れていくのではなく、
各セル毎に
14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13
4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3
9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8
などと、始まりの数字を変えることができれば、
0 | 1 | 2 | 3 | |
0 | 1 | * | * | * |
1 | * | 1 | * | * |
2 | * | * | * | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 1 | * | * | * | * |
1 | * | 1 | * | * | * |
2 | * | * | * | * | * |
3 | * | * | * | * | * |
4 | * | * | * | * | * |
のような数字の重複を防ぐことが出来て、
0 | 1 | 2 | 3 | |
0 | 14 | * | * | * |
1 | * | 4 | * | * |
2 | * | * | 9 | * |
3 | * | * | * | * |
0 | 1 | 2 | 3 | 4 | |
0 | 24 | * | * | * | * |
1 | * | 7 | * | * | * |
2 | * | * | 11 | * | * |
3 | * | * | * | 18 | * |
4 | * | * | * | * | * |
早い段階の破綻を防ぐことが出来ます。
それぞれの場合、
0 | 1 | 2 | 3 | |
0 | 14 | * | * | * |
1 | * | 4 | * | * |
2 | * | * | 9 | * |
3 | * | * | * | 7 |
0 | 1 | 2 | 3 | 4 | |
0 | 24 | * | * | * | * |
1 | * | 7 | * | * | * |
2 | * | * | 11 | * | * |
3 | * | * | * | 18 | * |
4 | * | * | * | * | 5 |
1つ前に戻って修正をし続ける必要がなく、
圧倒的に効率が良くなります。
では、各セル毎の始まりの数字を変えるにはどうしたらよいでしょうか。