第9講 配列とfor文を利用して3次魔方陣を作ろう
第7話 3次魔方陣の自動生成プログラム
public class A{
public static void main(String args[]){
f();
}
public static void f(){
int i,j,k,l,m,n,o,p,q,w,w1,w2;
int[][] a=new int[3][3];
for(i=1;i<10;i++){
a[0][0]=i;
for(j=1;j<10;j++){
a[0][1]=j;
if(a[0][1]!=a[0][0]){
for(k=1;k<10;k++){
a[0][2]=k;
w=a[0][0]+a[0][1]+a[0][2];
if(a[0][2]!=a[0][0] && a[0][2]!=a[0][1] && w==15){
for(l=1;l<10;l++){
a[1][0]=l;
if(a[1][0]!=a[0][0] && a[1][0]!=a[0][1] && a[1][0]!=a[0][2]){
for(m=1;m<10;m++){
a[1][1]=m;
if(a[1][1]!=a[0][0] && a[1][1]!=a[0][1] && a[1][1]!=a[0][2] && a[1][1]!=a[1][0]){
for(n=1;n<10;n++){
a[1][2]=n;
w=a[1][0]+a[1][1]+a[1][2];
if(a[1][2]!=a[0][0] && a[1][2]!=a[0][1] && a[1][2]!=a[0][2] && a[1][2]!=a[1][0] && a[1][2]!=a[1][1] && w==15){
for(o=1;o<10;o++){
a[2][0]=o;
w=a[0][0]+a[1][0]+a[2][0];
w1=a[0][2]+a[1][1]+a[2][0];
if(a[2][0]!=a[0][0] && a[2][0]!=a[0][1] && a[2][0]!=a[0][2] && a[2][0]!=a[1][0] && a[2][0]!=a[1][1] && a[2][0]!=a[1][2] && w==15 && w1==15){
for(p=1;p<10;p++){
a[2][1]=p;
w=a[0][1]+a[1][1]+a[2][1];
if(a[2][1]!=a[0][0] && a[2][1]!=a[0][1] && a[2][1]!=a[0][2] && a[2][1]!=a[1][0] && a[2][1]!=a[1][1] && a[2][1]!=a[1][2] && a[2][1]!=a[2][0] && w==15){
for(q=1;q<10;q++){
a[2][2]=q;
w=a[0][0]+a[0][1]+a[0][2];
w1=a[2][0]+a[2][1]+a[2][2];
w2=a[0][0]+a[1][1]+a[2][2];
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1] && w==15 && w1==15 && w2==15){
System.out.print(a[0][0]);
System.out.print (" ");
System.out.print(a[0][1]);
System.out.print (" ");
System.out.print(a[0][2]);
System.out.println();
System.out.print(a[1][0]);
System.out.print (" ");
System.out.print(a[1][1]);
System.out.print (" ");
System.out.print(a[1][2]);
System.out.println();
System.out.print(a[2][0]);
System.out.print (" ");
System.out.print(a[2][1]);
System.out.print (" ");
System.out.print(a[2][2]);
System.out.println();
System.out.println();
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
実行画面
3次魔方陣は8個ですべてです。
ただし、この8個よく見ると対称変換や回転変換させるとすべて重なります。
つまり、すべて合同です。
3次魔方陣は、本質的には1つです。
前に言った26次魔方陣は1兆の10乗を遙かに超える数があると言ったその数は、
対称変換や回転変換で重ねることのできない、本質的異なる26次魔方陣の個数です。
4次魔方陣で本質的に異なる魔方陣は880個、
5次魔方陣で約3億個です。
6次以降については現在いくつあるかわかっていません。
6次については推定で1.8×1019個だそうです。
さて、私がいった通り一瞬ですべての3次魔方陣をたたき出しました。
同様にして4次魔方陣でも880×8(本質的に異なる解は、鏡像や対称像など8つの合同な解をもつ)=7040個を
約10分程度でコマンドプロンプトへ掃き出します。
ですが、とうていfor文ではやる気が起きません。
何しろ16次元ループになってしまうのですから。
実は、関数の再帰的使用を使うと次数が異なっても対応できる普遍的なプログラムを簡単に作ることができます。
ですが、力業ではコンピュータの力をもってしても、4次魔方陣が限界です。
様々工夫が必要です。
工夫を重ねていくと、先に申し上げたとおり26次魔方陣でも1秒で数百の単位で生成できるようになります。
コンピュータ恐るべしです。
そして、プログラミングとは大変面白いものであることをがわかると思います。
ちょっとした工夫で、魔方陣作成速度は数百倍、数万倍、数兆倍、数京倍と信じられない勢いで伸びていきます。
プログラマーの腕によっては、スーパーコンピュータをもってしても10次魔方陣を作り出すことはできないのに対して、
腕によっては、パソコンでさえ200次魔方陣を簡単に作り出せるのです。
関数の再帰的呼び出しによるn次魔方陣の作成は第12講で予定してみます。
ただし、実際に現実的に可能なnは3,4,5のみです。
n=5が可能といっても解は約22億個(鏡像なども別に数えて)もあるので、
10個や100個などができたら途中で止めるという前提付きです。
6次以降も理論的には可能ですが、最初の1個がコマンドプロンプトに打ち出されるまで、
数時間も待たなければなりません。
次講では関数の再帰的呼び出しをテーマとします。
第6話へ 第10講第1話へ
VB講義へ
VB講義基礎へ
vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門
基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門
基礎から応用まで第2部
初心者のための
VC++による C言語 入門 C++ 入門 基礎から応用まで第3部
初心者のための Java 入門 サイト 基礎から応用まで第1部
初心者のための Java 入門 サイト 基礎から応用まで第2部
初心者のための Java 入門 サイト 基礎から応用まで第3部