マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第10章 関数の再帰的使用によって魔方陣を自動生成する

第1話 n次順列生成がどうして魔方陣自動生成や数独自動生成に直結するのか


第9章第5話でn次順列の自動生成に成功しました。

これがなぜ、魔方陣の自動生成につながるのでしょうか。

理由は
123456789 123456798 123456879 123456798 ・・・を


と2次元に並べていって対角線合計・行合計・列合計が満たされていないときは、

再帰することを繰り返せば


対角線の条件を満たすものが見つかります。

次に、逆対角線に埋めていき、

逆対角線の合計が15になるまで再帰を繰り返せば、

対角線の条件を満たします。

そして、

まで行っても行の合計は15にはなりませんが、

再帰はいくらでも戻れます。

ダメであれば、より浅い方 = より外側の人形まで再帰してやり直せばよいのです。

潜航して上手くいかなければ、浅い方まで戻ってやり直す。

この繰り返しによって、魔方陣のすべてを発見できるのです。

潜水艦バトルと同じです。

危険性があれば急速潜航して、チャンスがあれば浅いところまで戻って魚雷を打つタイミングを図る

のが潜水艦バトルです。


3次魔方陣の場合は総数は8個です。

数学で研究する場合は対称移動や回転移動で重なるものは、

同一と見なされるので、

結局は解は1つしかないとされるのですが、

今の段階では1つでも異なれば別の解と見なすことにして、

3次魔方陣8個をすべて生成することを目指しましょう。

それが成功したら4次魔方陣7040個の全生成を目指します。

5次魔方陣の全生成は難しいので100個できた段階でプログラムを終了させます。

6次魔方陣についても総数がやっと数年前に発見されたほど難しく、

100個の生成で止めます。

因みに5次魔方陣は2億を超える総数があり、

6次魔方陣は国立大学工学部の教授が総数は京のレベル(具体的な数字は覚えていません)に達することを証明しています。

この教授は工学部教授とはいえ、6次魔方陣の総数のカウントは自分の専門と関係なく、

奥さんからどうしてそんなこと研究しているの?

と聞かれて答えられなかったのですが、

それでも研究を続けたというのです。

確か、3年ぐらい前に朝日新聞のほぼ1面を使って掲載されていました。

魔方陣を35年ぐらい研究してきた私にはその教授の悩みが痛いほどわかります。

そんなこと研究して何になるの?とよく生徒から聞かれたものです。

実用性はないけど研究をやめられない!という悩みが。


最後にもう3つ説明すべきことがあります。

まず、1次元配列の配置です。

はこのようにするときに、魔方陣は最も早く生成できます。

条件の厳しいところから埋めていくのは時間割編制のコツです。

条件の緩い駒はいくらでも移動が効くのに対して、

条件の厳しい駒は動かすことができないので、

厳しい方から埋めていく、

これは時間割編制の鉄則であると同時にパズルの攻略法でもあります。

魔方陣も数独もパズルです。

ですから、条件の厳しいところからクリアさせるのが鉄則となります。

ならば、配置は

ではないかと思う方は、頭の鋭い方です。

どちらが速いかは実験する以外に決着させることはできません。

図の真ん中は対角線合計・逆対角線合計・第2行合計・第2列合計の4条件を満たさなければならないので、

a[0]を真ん中に持ってくることは確かに一案です。


2番目はどのタイミングで合計処理をするかです。

あるいは

の前者なら

a[2]、a[4]、a[5]、a[7]、a[6]、a[8]、a[8]

a[8]が2回登場するのは、

第3行合計と第2列合計と2回合計チェックをしなければならないからです。

また、a[4]が2回登場するのは、

逆対角線合計と第1列合計を計算させなければならないからです。


後者も同じですね。

後には、3次魔方陣だけに通用する方法ではなく、

4次魔方陣・5次魔方陣・6次魔方陣でも通用する方法 = 普遍的方法 = 汎用性のある方法を考えていただきますが、

これは初心者には難しい課題ですので、これは後の課題として、

今はsが

2、4、5、7、6、8、8

のときに対角線または行または列の合計を計算させて

ただし、for文での取り組みではなく

int g = a[3] + a[1] + a[4];

というような形にしてください。

そして、15にならないときには再帰させてください。



3番目に

あるいは

の配置のときにコンソール画面でどの順で表示するかです。

前者の配列であれば、

a[0] → a[5] → a[3] → 改行 → a[6] → a[1] → a[7] → 改行 → a[4] → a[8] → a[2] → 改行

の順をたどります。

for文でやるにはどうしたらよいか、

すなわち、合計処理のときと同じように、

3次魔方陣だけに通用する方法ではなく、

4次魔方陣・5次魔方陣・6次魔方陣でも通用する方法 = 普遍的方法 = 汎用性のある方法を考えていただきたいのですが、

これは初心者には難しい課題ですから、後の課題として、

今は手作業で

a[0] → a[5] → a[3] → 改行 → a[6] → a[1] → a[7] → 改行 → a[4] → a[8] → a[2] → 改行

を実現してください。

さぁ、第9章第5話のコードを改良して

3次魔方陣の全生成に挑戦しましょう。


(
2 9 4
7 5 3
6 1 8

2 7 6
9 5 1
4 3 8

4 9 2
3 5 7
8 1 6

4 3 8
9 5 1
2 7 6

6 7 2
1 5 9
8 3 4

6 1 8
7 5 3
2 9 4

8 3 4
1 5 9
6 7 2

8 1 6
3 5 7
4 9 2

生成された3次魔方陣の総数は8です。
)














第9章第14話へ 第10章第2話へ

本講義トップへ