第16講 魔方陣作成の高速化(数万倍へ)

第9話 実験結果とそれに基づくVer.2完成一歩前版

実験結果による最適値

n  4  5  6 
Randomize()の括弧内の数字(シード値)  219 56 400
sh()の括弧内の数字  19
sh()の値  24 13

Ver.2コード
Dim mah(6, 6) As Byte, x(36) As Byte, y(36) As Byte
Dim n As Byte, cn As Integer
Private Sub CommandButton1_Click()
  Dim i, j As Integer
  n = Cells(3, 8)
  
Rnd (-1)
  If n = 4 Then Randomize (219)
  If n = 5 Then Randomize (56)
  If n = 6 Then Randomize (400)

  zhy

  sk = 0
  cn = 0
  ms (0)
  Cells(4, 12) = cn

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
  Dim ii As Integer, iii As Integer, kk As Byte

  a = x(g)
  b = y(g)
  ii = n * n * Rnd
  
If n = 4 Then kk = 7
  If n = 5 Then kk = 24
  If n = 6 Then kk = 13
  If n = 3 Then kk = 1

  For i = 0 To n * n - 1
    iii = (ii +
kk * i) Mod n * n



Ver.2が完成して、一応6次魔方陣まで作れるようになりました。
今回のコードでも自動実験を粘り強く続ければ7,8次あたりも出来るようになるかもしれません。
しかし、1個が出来るまでの時間はあっという間に出来ても1秒に数百個単位で作らせるとなると、
まだまだ改善が必要です。

実はすぐに第17講に入り、末項確定法に挑むつもりでしたが、
Ver.2の範囲内でもう一つ改良できることを思い出しました。
よく考えてみると、
Sub ms(g As Byte)

  Dim i As Byte, j As Byte, k As Byte, a As Byte, b As Byte, w As Byte
  a = x(g)
  b = y(g)

  For i = 0 To n * n - 1
    mah(b, a) = i + 1
    
If g > 0 Then
      For j = 0 To g - 1
        If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
      Next
    End If

ピンクの部分は無駄があります。
毎回、今まで入力したものと重複がないか調べていますが、
そんなことをしなくても簡単に重複検査ができます。
例えば、グローバル配列p(i)を用意しておいて

10 11 〜  
 p(i) × × × × × × × × × × × ×

使っていない数字を×(実際には0)を入れておいて、その数字を使用したら○(実際には1)に変更し、
○が重なるときは重複と判定すればよいのです。
尚、配列の要素は0から始まりますので、p(mah(b,a)-1)としておくとよいでしょう。
ですから、表も数字がずれています。
今回の改良をもってVer.2の完成とします。



第8話へ 第10話へ

004
  

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

数学研究室に戻る