第9講 4次魔方陣と6次魔方陣の作成
第6話 andとorの否定


解答例
for(i=0;i<3;i++){
  for(j=0;j<3;j++){
    if((i!=j) && (i!=3-j) ){
      v=a[i][j];
      a[i][j]=a[3-i][3-j];
      a[3-i][3-j]=v;
    }
  }
}

(コピーペースト用
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if((i!=j) && (i!=3-j) ){
v=a[i][j];
a[i][j]=a[3-i][3-j];
a[3-i][3-j]=v;
}
}
}


解説

一般に、条件
pまたはq
の否定は、
(pでない)かつ(qでない)
になります。
また、pかつqの否定は
(pでない)または(qでない)
となります。

「かつ」という言葉に聞き慣れていない人もいると思いますが、
pかつq
は条件pも条件qも同時に満たすことを表します。

それに対して、
pまたはq
は条件pを満たすか、条件qを満たしていればよいのです。
どちらか一方の条件を満たしていればよいのですから、
両方の条件を満たすpかつqの状態でもいいのです。

集合の図を書いてみましょう。
条件pを満たす集合をP、
条件qを満たす集合をQ、
pかつqを満たす集合をP∩Q、
pまたはqを満たす集合をP∪Qと表すことにしますと、
下図のようになります。



したがって、条件pまたはqの否定を表す集合は、

となり、条件pまたはqの否定は(pでない)かつ(qでない)となります。
また、条件pかつqの否定を表す集合は、

となり、条件pかつqの否定は(pでない)または(qでない)になります。

以上の解説から
(i==j) || (i==3-j)の否定は、
(i!=j) && (i!=3-j) であることがご理解頂けるかと思います。

for(i=0;i<3;i++){
  for(j=0;j<3;j++){
    if((i!=j) && (i!=3-j) ){
      v=a[i][j];
      [i][j]=a[3-i][3-j];
      a[3-i][3-j]=v;
    }
  }
}
をトレースしてみましょう。
for(i=0;i<3;i++){
  for(j=0;j<3;j++)
から、i、jの動いていく範囲は
です。さらに、if((i!=j) && (i!=3-j) )
によって、対角線と逆対角線が除外されますので、動く範囲はさらにに限定され、
となります。
それらのセルが

と交換されます。
なお、
for(i=0;i<4;i++){
  for(j=0;j<4;j++){
    if((i!=j) && (i!=3-j) ){
      v=a[i][j];
      [i][j]=a[3-i][3-j];
      a[3-i][3-j]=v;
    }
  }
}
としてしまうと、交換対象セルが
となってしまい、2度交換され元に戻っていまいますので、注意しましょう。
例えば、i=0、j=1のとき
が交換され、
となりますが、
i=3、j=2のとき
が再び交換され、
と元に戻ってしまうのです。
だから、
for(i=0;i<3;i++){
  for(j=0;j<3;j++){
    if((i!=j) && (i!=3-j) ){
      v=a[i][j];
      a[i][j]=a[3-i][3-j];
      a[3-i][3-j]=v;
    }
  }
}
でなければならないのです。

具体的にトレースしてみましょう。
T i=0 の場合
 @ j=0のとき、
   i=0、j=0よりi=jなので、条件(i!=j) && (i!=3-j)に抵触し、if文は実行されません。
 A j=1のとき
   i=0、j=1で条件(i!=j) && (i!=3-j)がクリアされ、if文が実行されます。
   v=a[0][1];
   a[0」[1]=a[3][2];
   a[3][2]=v;  により
が交換される。
 B j=2のとき、
    i=0、j=2なので条件(i!=j) && (i!=3-j)がクリアされ、if文は実行されて、
    v=a[0][2];
    a[0」[2]=a[3][1];
    a[3][1]=v;  により
が交換される。
U i=1 の場合
 @ j=0のとき、
   i=1、j=0なので条件(i!=j) && (i!=3-j)をクリアして、if文が実行され、
   v=a[1][0];
   a[1」[0]=a[2][3];
   a[2][3]=v;  により
の交換が実行される。
 A j=1のとき
   i=j=1となり、条件(i!=j) && (i!=3-j)がクリアされず、if文は実行されません。
 B j=2のとき、
   i=1、j=2なのでi=3-jとなり、
   条件(i!=j) && (i!=3-j)がクリアされず、if文は実行されません。
V i=2 の場合
 @ j=0のとき、
   i=2、j=0なので条件(i!=j) && (i!=3-j)をクリアして、if文が実行され、
   v=a[2][0];
   a[2」[0]=a[1][3];
   a[1][3]=v;  により
の交換が実行される。
 A j=1のとき
   i=2、j=1なのでi=3-jとなり、条件(i!=j) && (i!=3-j)がクリアされず、if文は実行されません。
 B j=2のとき、
   i=2、j=2なのでi=jとなり、
   条件(i!=j) && (i!=3-j)がクリアされず、if文は実行されません。
   

以上より

 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15 16

      

 1 15 14  4
12  6  7  9
 8 10 11  5
13  3  2 16

が成功していることがわかります。


以上で4次魔方陣は終わりにして、次に6次魔方陣に挑戦しましょう。
作り方を復習しておくと、

最初に自然配列を作ります。

 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

そして、

 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

ピンクは中心に対して点対称移動、
薄緑は中央の直線に対して上下に線対称移動、
紺色
は中央の直線に対して左右に線対称移動
を行います。すると、

36 32  4  3  5 31
12 29 27 10 26  7
19 17 22 21 14 18
13 20 16 15 23 24
25 11  9 28  8 30
 6  2 33 34 35  1


36 32  4  3  5 31
12 29 27 10 26  7
19 17 22 21 14 18
13 20 16 15 23 24
25 11  9 28  8 30
 6  2 33 34 35  1

では皆さん、4次魔方陣の作り方を参考にして6次魔方陣の作成に挑戦しましょう。

交換は、a[0][0]=a[5][5]のような手動ではなく、
for文で自動で行ってください。
繰り返しは、人間の行うものではありませんよ。
なかなか簡単にはいきませんが、粘り強く試行錯誤を繰り返しましょう。
完成したら、第7話をクリックしましょう。
繰り返しますが、あくまで解答例であって第7話と同じである必要はありませんよ。
for文を使っていて(今回は条件が指定されているからです)6次魔方陣ができていればどんなプログラミングでも正解です。
ただ、異なるプログラミングをした場合でも第7、8話は参考になるはずですから必ず熟読してください。


第5話へ 第7話へ



初心者のためのjava 入門 基礎から応用まで
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすい vb 入門 vba 入門 基礎から応用まで 第1部
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ