第14講 ベクタを利用して6次魔方陣を作ろう!
第7話 第2のコードのミソ
void g(vector<vector<int>>::iterator m){
int w;
for(int i=0;i<3;i++){ //対角線交換
for(int j=0;j<6;j++){
if(i==j || 5-j==i){
w=m[5-i][5-j];
m[5-i][5-j]=m[i][j];
m[i][j]=w;
}
}
}
}
このコードを理解するには、
m[i][i]が右下がりの対角線を動き、
m[5-i][i]が右上がりの対角線を動く、
ことを把握しなければなりません。
m[i][i]は座標(i,i)に対応し
m[5-i][i]は座標(5-i,i)に対応しているからです。
座標(i,i)とき、
0 | 1 | 2 | 3 | 4 | 5 | |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 7 | 8 | 9 | 10 | 11 | 12 |
2 | 13 | 14 | 15 | 16 | 17 | 18 |
3 | 19 | 20 | 21 | 22 | 23 | 24 |
4 | 25 | 26 | 27 | 28 | 29 | 30 |
5 | 31 | 32 | 33 | 34 | 35 | 36 |
左上から右下に動いていきます。
座標(5-i,i)とき、
0 | 1 | 2 | 3 | 4 | 5 | |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 7 | 8 | 9 | 10 | 11 | 12 |
2 | 13 | 14 | 15 | 16 | 17 | 18 |
3 | 19 | 20 | 21 | 22 | 23 | 24 |
4 | 25 | 26 | 27 | 28 | 29 | 30 |
5 | 31 | 32 | 33 | 34 | 35 | 36 |
左下から右上に動いていきます。
尚、座標(i,5-i)の場合には
右上から左下へと逆の動きをします。
if(i==j || 5-j==i)の
i==jの場合、
w=m[5-i][5-j];
m[5-i][5-j]=m[i][j];
m[i][j]=w;
は
w=m[5-i][5-i];
m[5-i][5-i]=m[i][i];
m[i][i]=w;
であり、
座標(5-i,i)バージョン
0 | 1 | 2 | 3 | 4 | 5 | |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 7 | 8 | 9 | 10 | 11 | 12 |
2 | 13 | 14 | 15 | 16 | 17 | 18 |
3 | 19 | 20 | 21 | 22 | 23 | 24 |
4 | 25 | 26 | 27 | 28 | 29 | 30 |
5 | 31 | 32 | 33 | 34 | 35 | 36 |
に対応します。
if(i==j || 5-j==i)の
5-j==iの場合、j==5-iであることに注意すれば
w=m[5-i][5-j];
m[5-i][5-j]=m[i][j];
m[i][j]=w;
は
w=m[5-i][i];
m[5-i][i]=m[i][5-i];
m[i][5-i]=w;
であり、
座標(5-i,i)バージョン
0 | 1 | 2 | 3 | 4 | 5 | |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 7 | 8 | 9 | 10 | 11 | 12 |
2 | 13 | 14 | 15 | 16 | 17 | 18 |
3 | 19 | 20 | 21 | 22 | 23 | 24 |
4 | 25 | 26 | 27 | 28 | 29 | 30 |
5 | 31 | 32 | 33 | 34 | 35 | 36 |
に対応します。
void g(vector<vector<int>>::iterator m){
int w;
for(int i=0;i<3;i++){ //対角線交換
for(int j=0;j<6;j++){
if(i==j || 5-j==i){
w=m[5-i][5-j];
m[5-i][5-j]=m[i][j];
m[i][j]=w;
}
}
}
}
摩訶不思議に思えたこのコードも
i==jのときは、jをiに置き換えれば、
w=m[5-i][5-i];
m[5-i][5-i]=m[i][i];
m[i][i]=w;
5-j==iときは、5-jをi、jを5-iと置き換えれば、
w=m[5-i][i];
m[5-i][i]=m[i][5-i];
m[i][5-i]=w;
常識的な姿に姿態します。
結局、
void g(vector<vector<int>>::iterator m){
int w;
for(int i=0;i<3;i++){ //対角線交換
for(int j=0;j<6;j++){
if(i==j || 5-j==i){
w=m[5-i][5-j];
m[5-i][5-j]=m[i][j];
m[i][j]=w;
}
}
}
}
は
void g(vector<vector<int>>::iterator m){
int w;
for(int i=0;i<3;i++){ //対角線交換
w=m[5-i][5-i];
m[5-i][5-i]=m[i][i];
m[i][i]=w;
}
for(int i=0;i<3;i++){ //逆対角線交換
w=m[5-i][i];
m[5-i][i]=m[i][5-i];
m[i][5-i]=w;
}
}
と同じであることが明らかになったわけです。
第2のコードの謎が明らかになりました。
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 |
では、左右の対称移動
すなわち、紺色のセルの交換をするにはどうしたらよいでしょうか。
ヒントを第8話で述べることにしましょう。
第6話へ 第8話へ
eclipse c++ 入門講義第1部へ
魔方陣 数独で学ぶ VBA 入門
数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 C++ 入門 基礎から応用まで第1部
eclipse java 入門
java 入門 サイト 基礎から応用まで
VC++ C言語 C++ 入門 初心者 基礎から応用まで
本サイトトップへ