第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です。

4
10 11
12 13 14
15 16 17 18
19 20 21
4 22 23 24

では
               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つでは何をしているのでしょう。

4
10 11
12 13 14
15 16 17 18
19 20 21
4 22 23 24


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

10 11
12 13
14 15


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は対象にならず、
範囲は下表の通りになります。

10 11
12 13
14 15



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が加わりますから、対象範囲は、

10 11
12 13
14 15


左表の紺色のところです。















n=5のときは
g>3×5−4=11ですから範囲は、

4
10 11
12 13 14
15 16 17 18
19 20 21
4 22 23 24


の通りです。

















第19講第4話へ 第19講第6話へ



VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座