第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話へ

004
  

VBA講義第1部へ
vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ

数学研究室に戻る