第17講 末項確定法(魔方陣作成マクロVer.3)への挑戦

第4話 Ver.2とVer.3の時間計測版

Ver.2時間計測版コード例
Dim mah(6, 6) As Byte, x(36) As Byte, y(36) As Byte, p(36) As Byte
Dim n As Byte, cn As Integer
Private Sub CommandButton1_Click()
  Dim i, j As Integer
  
Dim hj As Date, ow As Date
  
hj = Timer
  n = Cells(3, 8)
  Rnd (-1)
  If n = 4 Then Randomize (219)
  If n = 5 Then Randomize (56)
  If n = 6 Then Randomize (400)
  syokika
  zhy
  sk = 0
  cn = 0
  ms (0)
  
ow = Timer
  Cells(1, 28) = (ow - hj) / 10

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 Byte, h As Byte
  Dim ii As Integer, iii As Integer, kk As Byte
  
If cn = 100 Then Exit Sub
        ・
        ・
        ・
    If g + 1 < n * n Then
      sk = sk + 1
      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
      
If cn = 100 Then Exit Sub
    End If
tobi:
    If h = 1 Then p(mah(b, a) - 1) = 0
  Next

End Sub


Ver.3時間計測版コード例
Dim mah(6, 6) As Byte, x(36) As Byte, y(36) As Byte, p(36) As Byte
Dim n As Byte, cn As Integer
Private Sub CommandButton1_Click()
  Dim i, j As Integer
  Dim hj As Date, ow As Date
  hj = Timer
  n = Cells(3, 8)
  Rnd (-1)
  If n = 4 Then Randomize (425)
  If n = 5 Then Randomize (24)
  If n = 6 Then Randomize (4768)
  syokika
  zhy
  sk = 0
  cn = 0
  ms (0)
  ow = Timer
  Cells(1, 28) = (ow - hj) / 10

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 Byte, h As Byte
  Dim ii As Integer, iii As Integer, kk As Byte
  If cn = 10 Then Exit Sub
        ・
        ・
        ・
  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
      
If cn = 10 Then Exit Sub
    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
        ・
        ・
        ・
    End If
tobi:
    If h = 1 Then p(mah(b, a) - 1) = 0
  Next

End Sub


実験結果

表の中は1個あたりの平均算出時間 実験環境は、インテルCoreTM(3.20Ghz)650

次数 
Ver.2 0.077 6.708 76.62
Ver.3 0.023 1.129  11.64 
倍率  3.3  6.0  6.6

本当は、100個平均でデータをとりたいところですが、Ver.2だと6次は77×100=7700秒=約2時間6分もかかってしまいます。
今回はIf cn = 10 Then Exit SubCells(1, 28) = (ow - hj) / 10を見ればお分かりのように、
10個作成するのにかかる時間です。
今回は、6次までしか実験していませんが、
7次、8次と次数が進んでいくと倍率が高くなることが予想されます。
しかし、6次で6.6倍の高速化に成功したとはいえ、1個あたり6.6秒はとても褒められたものではありません。
次の講では、一般種法を取り入れてさらなる高速化を図ります。
次数によっては、10万倍以上の高速化が図れ、
私の記憶では12次魔方陣あたりまで、20秒以内で作れるようになります。
4次と5次と6次の作成時間を比較すれば、
次数がひとつ上がるだけで、難度が極めて大きくなることがわかります。
しかも、次数のひとつ差に対する難度の差は次数が大きくなるほど大きくなります。
10次魔方陣あたりでは、シード値をどのように工夫しても1個作成するのに、
Ver.3では10時間を切ることは出来ないでしょう。
それだけ、10次あたりでは難度が高いのです。
ですから、10万倍以上の高速化が図れても、12魔方陣あたりが限界なのです。
26次魔方陣など1秒で数百の単位で作らせるにはまだまだ改良が必要です。


ところで、Timerは現在時刻を取得する関数です。
時刻を収納する変数のタイプは
Dateです。

Ver.2時間計測版 Ver.3時間計測版


第3話へ 第18講第1話へ

004
  

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

数学研究室に戻る