第19講 対角線法による魔方陣自動生成ソフトの高速化
第5話 対角線を先に入力する!

vee
qcq
qwqZ
を実現するプログラム例
Dim a(10, 10) As Byte, n As Byte, cn As Long, y(100) As Byte, x(100) As Byte
Private Sub CommandButton1_Click()

  CommandButton2_Click
  cn = 0
  n = Cells(4, 2)
  Call zy
  Call f(0) 'n次魔方陣作成プロシージャ
End Sub

Sub zy()

  Dim i As Byte, j As Byte, k As Byte
  Dim b(10, 10) As Byte
  
  For i = 0 To n - 1
    For j = 0 To n - 1
      b(i, j) = n * n + 1
    Next
  Next
  For i = 0 To n - 1
    b(i, i) = i
  Next
  k = n
  For i = 0 To n - 1
    If b(i, n - 1 - i) = n * n + 1 Then
      b(i, n - 1 - i) = k
      k = k + 1
    End If
  Next
  For i = 0 To n - 1
    For j = 0 To n - 1
      If b(i, j) = n * n + 1 Then
        b(i, j) = k
      k = k + 1
    End If
    Next
  Next
  
  For i = 0 To n - 1
    For j = 0 To n - 1
      y(b(i, j)) = i
      x(b(i, j)) = j
    Next
  Next

  
End Sub

Sub f(g As Byte)

  Dim i As Byte, j As Byte, w As Byte
  For i = 1 To n * n
    If g > 0 Then
      For j = 0 To g - 1
        If i = a(y(j), x(j)) Then GoTo tobi
      Next
    End If
    a(y(g), x(g)) = i
'    If x = n - 1 Then
'      w = 0
'      For j = 0 To n - 1
'        w = w + a(y, j)
'      Next
'      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
'    End If
'    If y = n - 1 Then
'      w = 0
'      For j = 0 To n - 1
'        w = w + a(j, x)
'      Next
'      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
'    End If
'    If x = 0 And y = n - 1 Then
'      w = 0
'      For j = 0 To n - 1
'        w = w + a(j, n - 1 - j)
'      Next
'      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
'    End If
'    If x = n - 1 And y = n - 1 Then
'      w = 0
'      For j = 0 To n - 1
'        w = w + a(j, j)
'      Next
'      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
'    End If

    If g + 1 < n * n Then
      Call f(g + 1)
      If cn = 1 Then Exit Sub
    Else
      Call h
      If cn = 1 Then Exit Sub
    End If
tobi:
  Next
  
End Sub

Sub h()

  Dim i As Byte, j As Byte, s As Byte, am As Byte, w As Byte
    
  For i = 0 To n * n - 1
    s = Int(i / n)
    am = i Mod n
    Cells(6 + s + (n + 1) * Int(cn / 5), 2 + am + (n + 1) * (cn Mod 5)) = a(s, am)
  Next
  cn = cn + 1
  
tobi:
  
End Sub

Private Sub CommandButton2_Click()
  
  Rows("5:20000").Select
  Selection.ClearContents
  Cells(1, 1).Select
  
End Sub
参考ダウンロード添付ファイル


0 1 2 3 4
0 0 9 10 11 5
1 12 1 13 6 14
2 15 16 2 17 18
3 19 7 20 3 21
4 8 22 23 24 4

白い数字と座標(表の)と座標(表の)が関連づけは、
  For i = 0 To n - 1
    For j = 0 To n - 1
      y(b(i, j)) = i
      x(b(i, j)) = j
    Next
  Next

によってできます。
私には全く思いもおよばない見事な方法です。

例えば、i = 4  j = 1 のときb(4,1)は22です。
ですから、
      y(22) = 4
      x(22) =
1

で確かに逆対応が出来ていますね。

仮屋崎さん実にお見事です。


では、保留しておいた、
行合計・列合計・対角線合計の各検査を復活させましょう。
検査を行う場所は、

0 1 2 3 4
0 0 9 10 11 5
1 12 1 13 6 14
2 15 16 2 17 18
3 19 7 20 3 21
4 8 22 23 24 4

と色のついている部分です。
対角線から先に入れることによって、
大変高速化しますが、
その分プログラムは複雑になってしまいます。

ですが、ここまでついて優秀な皆さんなら、
出来るはずです。
頑張りましょう。
この工夫によって、
5次魔方陣ならおそらく数千倍クラス、
6次魔方陣であれば数万倍クラスの高速化が実現しますが、
それでも、6次魔方陣には歯が立ちませし、
5次魔方陣をすべて生成させようとしたら、
宇宙時間ほどかかります。
ですから、nの入力は5次までとして、
4次のときは100個、
5次のときは50個、
魔方陣が生成できたときには、
プログラムを止めるようにしましょう。
また、時間計測機能も付け加え、
生成された魔方陣個数も表示しましょう。
魔方陣の個数は、終わってから表示するのではなく、
出来る度にリアルタイムに表示して途中経過が分かるようにしましょう。

xwqet
uguygy
wewsx



第4話へ 第6話へ
004

eclipse c++ 入門
魔方陣 数独で学ぶ VBA 入門
数独のシンプルな解き方・簡単な解法の研究
vc++講義へ
excel 2013 2010 2007 vba入門へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
専門用語なしの C言語 C++ 入門(Visual C++ 2010で学ぶ C言語 C++ 入門)
専門用語なしの excel vba マクロ 入門 2013 2010 2007 対応講義 第1部
eclipse java 入門へ
excel 2016 vba 入門へ
小学生からエンジニアまでのRuby入門へ
本サイトトップへ