第16講 全セルリスト構造解析(全体リスト構造解析)によって数独(ナンプレ)を解く
第12話 全体構造解析=全セルリスト構造解析の繰り返しを最初の数セルに限定すると?
プログラム例
Dim mah(8, 8) As Byte, lst(8, 8, 8) As Byte, mx(8, 8) As Byte, h(8, 8, 8) As Byte, cn As Byte
Dim gh As Byte
Private Sub CommandButton1_Click()
  
  Dim i As Byte, j As Byte, hajime As Variant, owari As Variant
  gh = 4
  hajime = Timer
  dainyuu
  cn = 0
  syokika
  For i = 0 To 8
    For j = 0 To 8
      If mah(i, j) = 0 Then
        Call cellkaiseki1(i, j)
        Call cellkaiseki2(i, j)
      End If
    Next
  Next
  f (0)
  hyouji
  owari = Timer
  Cells(7, 13) = "解くのにかかった時間は"
  Cells(8, 13) = owari - hajime
  Cells(9, 13) = "秒です。"

End Sub

Sub dainyuu()
  
  Dim i As Byte, j As Byte
  For i = 0 To 8
    For j = 0 To 8
      If Cells(4 + i, 2 + j) = "" Then mah(i, j) = 0 Else mah(i, j) = Cells(4 + i, 2 + j)
    Next
  Next
  
End Sub

Sub hyouji()
  
  Dim i As Byte, j As Byte, k As Byte
  
  For i = 0 To 8
    For j = 0 To 8
      Cells(14 + i, 2 + j) = mah(i, j)
    Next
  Next
  
End Sub

Sub syokika()

  Dim i As Byte, ja As Byte, k As Byte
  
  For i = 0 To 8
    For j = 0 To 8
      For k = 0 To 8
        h(i, j, k) = 1
'        lst(i, j, k) = k + 1
      Next
    Next
  Next
  
End Sub

Sub cellkaiseki1(i As Byte, j As Byte)
  
  Dim k As Byte, l As Byte
  
  For k = 0 To 8
    If mah(i, k) > 0 Then h(i, j, mah(i, k) - 1) = 0
  Next
  
  For k = 0 To 8
    If mah(k, j) > 0 Then h(i, j, mah(k, j) - 1) = 0
  Next
  
  For k = 0 To 2
    For l = 0 To 2
      If 3 * Int(i / 3) + k <> i And 3 * Int(j / 3) + l <> j Then
        If mah(3 * Int(i / 3) + k, 3 * Int(j / 3) + l) > 0 Then h(i, j, mah(3 * Int(i / 3) + k, 3 * Int(j / 3) + l) - 1) = 0
      End If
    Next
  Next

End Sub

Sub cellkaiseki2(i As Byte, j As Byte)
  
  Dim k As Byte, w As Byte
  
  w = 0
  For k = 0 To 8
    If h(i, j, k) = 1 Then
      lst(i, j, w) = k + 1
      w = w + 1
    End If
  Next
  mx(i, j) = w
  For k = 0 To 8
    If h(i, j, k) = 0 Then
      lst(i, j, w) = k + 1
      w = w + 1
    End If
  Next
  
End Sub
Sub f(g As Byte)
  
  Dim i As Byte, j As Byte, k As Byte
  Dim y As Byte, x As Byte
  
  y = Int(g / 9)
  x = g Mod 9
  
  If mah(y, x) > 0 Then
    If g + 1 < 81 Then
      f (g + 1)
      If cn = 1 Then Exit Sub
      Exit Sub
    Else
      cn = cn + 1
      hyouji
      If cn = 1 Then Exit Sub (2014/12/07に訂正)
    End If
  End If
  If mah(y, x) = 0 Then
    If mx(y, x) = 0 Then Exit Sub
    For i = 0 To mx(y, x) - 1
      mah(y, x) = lst(y, x, i)
      If g + 1 >= gh Then
        For j = 0 To 8
          If j <> x Then
            If mah(y, x) = mah(y, j) Then GoTo tobi
          End If
        Next
        For j = 0 To 8
          If j <> y Then
            If mah(y, x) = mah(j, x) Then GoTo tobi
          End If
        Next
        For k = 0 To 2
          For l = 0 To 2
            If y <> 3 * Int(y / 3) + k And x <> 3 * Int(x / 3) + l Then
              If mah(y, x) = mah(3 * Int(y / 3) + k, 3 * Int(x / 3) + l) Then GoTo tobi
            End If
          Next
        Next
      End If
      If g + 1 < 81 Then
        If g + 1 < gh Then
          syokika
          For j = 0 To 8
            For k = 0 To 8
              If mah(j, k) = 0 Then
                Call cellkaiseki1(j, k)
                Call cellkaiseki2(j, k)
              End If
            Next
          Next
        End If
        f (g + 1)
        If cn = 1 Then Exit Sub
      Else
        cn = cn + 1
        hyouji
        If cn = 1 Then Exit Sub
        If g < gh Then
          mx(y, x) = 0
          syokika
          For j = 0 To 8
            For k = 0 To 8
              If mah(j, k) = 0 Then
                Call cellkaiseki1(j, k)
                Call cellkaiseki2(j, k)
              End If
            Next
          Next
        End If
      End If
tobi:
    Next
  End If
  mah(y, x) = 0
  
End Sub

Private Sub CommandButton2_Click()
  
  Rows("14:200").Select
  Selection.ClearContents
  Range("M5", "V9").Select
  Selection.ClearContents
  Cells(2, 1).Select

End Sub


参考ファイル

実験結果 問題
問題について
繰り返さない場合
使う方
数字を入れる度に全体構造解析を繰り返した場合
実験結果
数セル限定した場合 gk=4の実験結果
結果1
gk=4ということは4セルまでに全体構造解析を繰り返すのを限定したということです。
いろいろ数値を変えて実験しても結果は思わしくありません。

セルに数字を入れる度に全セルについて構造解析を繰り返していますが、
明らかに無駄があります。
部分構造解析
例えば、セル(0,0)に
という数字を入れたときに,
影響を受けるのは色塗りをした部分だけです。
全セルについて構造解析をしてしまうのは全く必要のない
全体構造解析
オレンジの部分までリスト構造解析を行ってしまうということです。
リスト構造解析を
部分構造解析
必要な部分に限定して解析を行うことを、
部分構造解析=対象セル限定リスト構造解析と名付けています。
第17講では、この部分構造解析に取り組むことによって
第16講のソフトを高速化を図ります。

第11話へ 第17講第1話へ



トップ

初心者のためのc++ vc++ c言語 入門 基礎から応用までへ
初心者のための excel 2007 2010 2013 vba マクロ 入門 基礎から応用まで
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
vb講義トップへ
VB講義基礎へ
専門用語なしのC++入門へ
専門用語なしのJava入門へ
専門用語なしのVBA入門

数独のページ
魔方陣のページ
数学研究室に戻る
本サイトトップへ