第19講 特殊種による魔方陣ソフトの高速化
第5話 特殊種ソフトソース解説その3(列と行)
本日は
if(h==1){
if(n%2==1 && g>2*n-2){
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0;
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0;
}
if(n%2==0 && g>2*n-1){
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0;
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0;
}
if(h==1 && g>2*n-2 && x[g]>0){
for(j=0;j<x[g];j++){
if(a[y[g]][x[g]]==a[y[g]][j]){
h=0;
break;
}
}
}
}
if(h==1){
if(g>3*n-4){
if(h==1 && y[g]>0){
for(j=0;j<y[g];j++){
if(a[y[g]][x[g]]==a[j][x[g]]){
h=0;
break;
}
}
}
}
}
について解説していきます。
まず、
if(h==1){
if(n%2==1 && g>2*n-2){
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0;
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0;
}
if(n%2==0 && g>2*n-1){
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0;
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0;
}
if(h==1 && g>2*n-2 && x[g]>0){
for(j=0;j<x[g];j++){
if(a[y[g]][x[g]]==a[y[g]][j]){
h=0;
break;
}
}
}
}
から。
ここは列の重複検査を主な課題とするソースです。
最初の2つの範囲は奇数の場合と偶数の場合で違います。
まず奇数から見ていきましょう。
奇数の場合、範囲指定はg>2*n-2となっています。5次を例にすると具体的には、
g>2×5−2=9です。
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 |
では
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0;
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0;
の4つでは何をしているのでしょう。
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 |
12 |
を例にとると
0,1,6,8と比べています。
対角線と逆対角線にはすでに数字が入るからです。
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0; で0と
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0; で1と
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0; で6と
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0; で8と
比較しているわけです。
12 |
と同じ行上の対角線セル、逆対角線セル
同じく同じ列上の対角線セル、逆対角線セル
と比較をしているのです。
次に偶数の場合を見てみましょう。n=4の場合でトレースしましょう。
g>2*n-1はg>2×4−1=7
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
if(a[y[g]][x[g]]==a[x[g]][x[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][y[g]])h=0;
if(h==1)if(a[y[g]][x[g]]==a[y[g]][n-y[g]-1])h=0;
if(h==1)if(a[y[g]][x[g]]==a[n-x[g]-1][x[g]])h=0;
の4つの役割は、奇数の場合と同じです。
if(h==1 && g>2*n-2 && x[g]>0){
for(j=0;j<x[g];j++){
if(a[y[g]][x[g]]==a[y[g]][j]){
h=0;
break;
}
}
}
では、奇数と偶数を区別する必要がありません。
奇数の規定のg>2*n-2 でよいのです。
x[g]>0の規定が追加されるので、偶数の場合でも問題ありません。
例えばn=4のとき、g>2×4−2=7ですが、
g=7のときは、x=0(下表の赤がx)ですから、g=7は対象にならず、
範囲は下表の通りになります。
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
n=4の場合で例示しましたが、nは5,6,7,8,9,・・・等何でもよいことを
皆さん確認して下さい。
ここで行っている検査は、列の重複検査です。
対角線上のセルや逆対角線上のセルとの比較は、2回繰り返され、多少無駄があります。
ですから、重複をifで重複を取り除くとよいかもしれません。
読者の皆さんは考えてみてください。
最後に
if(h==1){
if(g>3*n-4){
if(h==1 && y[g]>0){
for(j=0;j<y[g];j++){
if(a[y[g]][x[g]]==a[j][x[g]]){
h=0;
break;
}
}
}
}
}
を解説しましょう。
ここでは行の重複検査をしています。
n=4とn=5の場合でトレースしますが、
その他でも同様に成り立つことはご自分で確認して下さい。
まず、n=4のとき、
g>3×4−4=8ですが、さらにy[g]>0が加わりますから、対象範囲は、
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
左表の紺色のところです。
n=5のときは
g>3×5−4=11ですから範囲は、
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 |
の通りです。
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座