第18講 一般種法×末項確定法(魔方陣作成マクロVer.4)への挑戦
第10話 衝撃の結末!
まさに予想外・想定外の驚愕天地の展開になったこと報告します。
前話でVer.4の完成を報告しました。
体感では、第6話の予想外の展開でしめしたプログラムに比べ遅いような気がして、
時間計測実験をすると、
Subプロシージャを2つに分解(n進数のnの位と1の位に分解)するより、
分割しないで直接1からn*nまで扱うSubプロシージャの方が遙かに速いという結果になってしまいました。
要素に分析した方が、速いという思い込みから1度の第6話の方式を実験していませんでしたが、
今回Ver.4の開発途中で、プログラミングがうまくいっているか試しに実験してわかった事実です。
分析ー総合の方法より、分析しないで直接探索する方が速いとは、夢にも思いませんでした。
結局速くなった理由は、一般種法にあったのではなくそのために開発した番号付けの方にあったのです。
私の魔方陣研究の方向を変更しなければならないのでは、と考えさせられる結果になりました。
なぜなら、分析ー総合の方法こそが魔方陣プログラムの最良の方法であると思っていたからです。
分析ー総合の方法を思いついたことが私の自慢の1つだったのですが、
これが私の桎梏(手かせ・足かけ)になっていたとは驚きです。
私は、20数年間も分析ー総合に囚われに身になっていたのです。
最良の方法と思っていたものに縛られていたのです。
しかし、今回の想定外の結果は私の魔方陣研究に新しい光を当てることになりました。
私が作った最速プログラムである細胞構成法(26次魔方陣あたりを1秒で何百という単位で作り出すプログラム)も、
より高速化が可能ということになります。
なぜなら、細胞構成法も結局は分析ー総合の圏内にあるからです。
今実験が終わったので、結果を示しましょう。
各バージョンが魔方陣を100個作るのにかかる時間の比較
4次の場合
Ver.3 | Ver.4 | Ver.3.5 |
1.76171875 | 1.27734375 | 1.841796875 |
5次の場合
Ver.3 | Ver.4 | Ver.3.5 |
222.1396484 | 5.952148438 | 4.94140625 |
6次の場合
Ver.3 | Ver.4 | Ver.3.5 |
1672.333984 | 99.78515625 | 23.95703125 |
ここでVer.3.5と表記しているものは、第6話の方式です。
Ver.4が勝てたのは4次魔方陣だけです。6次では完敗です。
実験は、6次までしかやりませんでしたが、
7次、8次と次数が上がる度に差が開いていくことは簡単に予想できることです。
したがって、一般種法×末項確定法はVer.4の名称のままにして、
第6話の方式(上の表のVer.3.5)Ver.5という名称を当てることにします。
Ver.5のコードも載せておきます。
Ver.5コード
Dim mah(12, 12) As Byte, x(144) As Byte, y(144) As Byte, p(144) As Byte, a(12, 12) As Integer
Dim n As Byte, cn As Integer, gk As Integer, tm As Byte
Private Sub CommandButton1_Click()
Dim i, j As Integer
n = Cells(3, 8)
Rnd (-1)
syokika
zhy
zhy1 (0)
'zhykakunin
ms (0)
End Sub
Sub syokika()
Dim i As Byte
Dim j As Byte
For i = 0 To n * n - 1
p(i) = 0
Next
tm = 0
sk = 0
cn = 0
gk = n
For i = 0 To n - 1
For j = 0 To n - 1
a(i, j) = -1
Next
Next
End Sub
Sub zhy()
Dim i As Byte
For i = 0 To n - 1
a(i, i) = i
Next
For i = 0 To n - 1
If a(i, n - 1 - i) = -1 Then
a(i, n - 1 - i) = gk
gk = gk + 1
End If
Next
End Sub
Sub zhy1(g As Byte)
Dim i As Byte
For i = g + 1 To n - 1
If a(g, i) = -1 Then
a(g, i) = gk
gk = gk + 1
End If
Next
zhy2 (g)
If tm = 1 Then Exit Sub
End Sub
Sub zhy2(g As Byte)
Dim i As Byte
Dim j As Byte
For i = g + 1 To n - 1
If a(i, g) = -1 Then
a(i, g) = gk
gk = gk + 1
End If
Next
If g + 1 < n Then
zhy1 (g + 1)
If tm = 1 Then Exit Sub
Else
For i = 0 To n - 1
For j = 0 To n - 1
y(a(i, j)) = i
x(a(i, j)) = j
Next
Next
tm = 1
Exit Sub
End If
End Sub
Sub ms(g As Byte)
Dim i As Integer, j As Byte, k As Byte, a As Byte, b As Byte, w As Integer, sa As Integer, h As Byte
Dim ii As Integer, iii As Integer, kk As Byte
a = x(g)
b = y(g)
If a = n - 1 And b = n - 1 Then
w = 0
For i = 0 To n - 2
w = w + mah(i, i)
Next
sa = Int(n * (n * n + 1) / 2) - w
If sa < 1 Or sa > n * n Then Exit Sub
If p(sa - 1) = 1 Then Exit Sub
mah(b, a) = sa
p(sa - 1) = 1
ms (g + 1)
p(sa - 1) = 0
Exit Sub
End If
If a = 0 And b = n - 1 Then
w = 0
For i = 0 To n - 2
w = w + mah(i, n - 1 - i)
Next
sa = Int(n * (n * n + 1) / 2) - w
If sa < 1 Or sa > n * n Then Exit Sub
If p(sa - 1) = 1 Then Exit Sub
mah(b, a) = sa
p(sa - 1) = 1
ms (g + 1)
p(sa - 1) = 0
Exit Sub
End If
If a = n - 2 And b = 0 Then
w = 0
For i = 0 To n - 3
w = w + mah(b, i)
Next
w = w + mah(b, n - 1)
sa = Int(n * (n * n + 1) / 2) - w
If sa < 1 Or sa > n * n Then Exit Sub
If p(sa - 1) = 1 Then Exit Sub
mah(b, a) = sa
p(sa - 1) = 1
ms (g + 1)
p(sa - 1) = 0
Exit Sub
End If
If a = 0 And b = n - 2 Then
w = 0
For i = 0 To n - 3
w = w + mah(i, a)
Next
w = w + mah(n - 1, a)
sa = Int(n * (n * n + 1) / 2) - w
If sa < 1 Or sa > n * n Then Exit Sub
If p(sa - 1) = 1 Then Exit Sub
mah(b, a) = sa
p(sa - 1) = 1
ms (g + 1)
p(sa - 1) = 0
Exit Sub
End If
If a = n - 1 And b > 0 And b < n - 1 Then
w = 0
For i = 0 To n - 2
w = w + mah(b, i)
Next
sa = Int(n * (n * n + 1) / 2) - w
If sa < 1 Or sa > n * n Then Exit Sub
If p(sa - 1) = 1 Then Exit Sub
mah(b, a) = sa
p(sa - 1) = 1
ms (g + 1)
p(sa - 1) = 0
Exit Sub
End If
If a > 0 And a < n - 1 And b = n - 1 Then
w = 0
For i = 0 To n - 2
w = w + mah(i, a)
Next
sa = Int(n * (n * n + 1) / 2) - w
If sa < 1 Or sa > n * n Then Exit Sub
If p(sa - 1) = 1 Then Exit Sub
mah(b, a) = sa
p(sa - 1) = 1
If g + 1 < n * n Then
ms (g + 1)
Else
For j = 0 To n - 1
For k = 0 To n - 1
Cells(6 + k + Int(cn / 10) * (n + 1), 1 + j + (cn Mod 10) * (n + 1)) = mah(j, k)
Next
Next
cn = cn + 1
Cells(4, 12) = cn
End If
p(sa - 1) = 0
Exit Sub
End If
ii = n * n * Rnd
If n = 4 Then kk = 3
If n = 5 Then kk = 13
If n = 6 Then kk = 11
If n = 3 Then kk = 1
For i = 0 To n * n - 1
iii = (ii + kk * i) Mod n * n
mah(b, a) = iii + 1
h = 0
If p(mah(b, a) - 1) = 1 Then GoTo tobi
If p(mah(b, a) - 1) = 0 Then
p(mah(b, a) - 1) = 1
h = 1
End If
ms (g + 1)
tobi:
If h = 1 Then p(mah(b, a) - 1) = 0
Next
End Sub
Private Sub CommandButton2_Click()
Rows("5:2000").Select
Selection.ClearContents
Cells(4, 12).Select
Selection.ClearContents
Cells(1, 1).Select
End Sub
ダウンロード用参考ファイル
第9話へ 第11話へ
VBA講義第1部へ
vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
数学研究室に戻る