第16講 魔方陣汎用的生成プログラムへの挑戦
第6話 魔方陣汎用的自動生成プログラム解説その2
コード再掲
f(0);
}
public static void f(int g){
if(cn>20)return;
int i,j,k,h;
for(i=1;i<n*n+1;i++){
h=1;
m[y[g]][x[g]]=i;
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][x[g]];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==0){
w=0;
for(j=0;j<n;j++){
w+=m[j][n-1-j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(g+1<n*n){
f(g+1);
if(cn>20)return;
}
else{
cn++;
for(j=0;j<n;j++){
for(k=0;k<n;k++){
if(m[j][k]<10){
System.out.print(" "+m[j][k]+" ");
}
else{
System.out.print(m[j][k]+" ");
}
}
System.out.println();
}
System.out.println();
if(cn>20)return;
}
}
}
}
}
本日はいよいよこのプログラムの核=メイン=エンジンの部分の解説です。
4次魔方陣ですと、トレースに10話程度かかってしまいますので、
3次魔方陣でトレースしていきます。
それでも相当息の長いトレースになりますので、
忍耐強くお読みなってください。
この難解なプログラムを読み際に注意しなければならない点は、
第10講 関数の再帰的呼び出し
第5話 関数の再帰的呼び出しによる汎用的順列作成プログラム解説その1
でも申し上げたとおり、gとiの役割の違いを明確にすることです。
この2つを明確に区別しないと、プログラムは訳のわからないものになってしまいます。
gはセル番号=空間識別番号であり、現在どこのセルを対象にしているかを示すものです。
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
つまり、上表のオレンジの番号に相当するものです。
そして、iはそこに入れる数字1から9です。
ビール瓶の例えでいえば、ビール瓶のラベルに相当するものがgであり、
瓶の中身であるビールに相当するのがiです。
引っ越しで使うダンボールを比喩とするならば、
ダンボールにマジックで下着などと書いてあるその文字に相当するのがgですし、
ダンボールの中に入っている下着に相当するのがiなのです。
iは1,2,3,4,5,6,7,8,9という数字であり、
gが0,1,2,3,4,5,6,7,8という数字なので、うっかりすると取り違えてしまいますが、
まったく別のものです。
gは空間識別番号でありセル番号です。
そして、関数の再帰的使用の場合入れ子式人形が3次魔方陣の場合9つできるわけですが、
入れ子式人形の番号です。ただし、外側から0番目、1番目、・・・というように0から数えます。
セル0と入れ子式人形0が対応しています。
セル番号と人形識別番号が一致しているのです。
ですから、gを空間を表す次元と呼びたいと思います。
9つのパラレルワールド(異世界)があり、gが変化することによってそのパラレルワールド(異世界)を行ったり来たりするのです。
gが異世界の次元番号を示すわけです。
そして、iはその異世界の中身です。
空間識別番号のgとその中身であるiを明確に区別して把握しないとこのプログラムは理解できません。
そして、各パラレルワールド(異世界)において、for文がそれぞれ実行され、iは1から9まで動くのです。
ですから、9次元ループになるのです。
理由は、入れ子式人形ですから、for文も入れ子式になるわけであるからです。
もちろん、4次魔方陣なら16次元ループ、5次魔方陣なら25次元ループ、6次魔方陣なら36次元ループ、
1000次魔方陣なら1000000次元ループになるのです。
1000000次元ループなどfor文では絶対に不可能ですね。
その高次元ループを可能にしているのが関数の再帰的使用=関数の自己再帰なのです。
関数の再帰的使用がいかに優れているかわかります。
第5話へ 第7話へ
VB講義へ
VB講義基礎へ
vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門
基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門
基礎から応用まで第2部
初心者のための
VC++による C言語 入門 C++ 入門 基礎から応用まで第3部