第16講 全セルリスト構造解析(全体リスト構造解析)によって数独(ナンプレ)を解く
第9話 別解の存在を確認するプログラム
プログラム訂正箇所
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)
Else
cn = cn + 1
hyouji
If cn = 1 Then Exit Sub (2014/12/07訂正)
End If
Exit Sub
End If
If mah(y, x) = 0 Then
For i = 0 To mx(y, x) - 1
mah(y, x) = lst(y, x, i)
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
If g + 1 < 81 Then
f (g + 1)
Else
cn = cn + 1
hyouji
End If
tobi:
Next
End If
mah(y, x) = 0
End Sub
訂正箇所は、
・
If mah(y, x) > 0 Then
If g + 1 < 81 Then
f (g + 1)
If cn = 1 Then Exit Sub
Else
cn = cn + 1
hyouji
If cn = 1 Then Exit Sub
End If
Exit Sub
End If
If mah(y, x) = 0 Then
For i = 0 To mx(y, x) - 1
mah(y, x) = lst(y, x, i)
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
If g + 1 < 81 Then
f (g + 1)
If cn = 1 Then Exit Sub
Else
cn = cn + 1
hyouji
End If
tobi:
Next
End If
mah(y, x) = 0
・
3カ所If cn = 1 Then Exit Subを削っただけです。
参考ファイル7
実行画面
別解がないかを確認すると、確認しない場合よりかなり時間がかかります。
市販されている数独(ナンプレ)は、別解のない適正な問題ですから、
If cn = 1 Then Exit Subは入れておきましょう。
If cn = 1 Then Exit Subを削らなければならない場面は、
数独の問題作成ソフトの開発において現れます。
数独(ナンプレ)のルールに基づいて、適当に数字を配置していっても、
ほとんどの場合は、解が存在しないか、複数解が存在するものになってしまいます。
作った問題が適正なものであるか調べるために、
解が複数個存在しないかのチェックは必然です。
ところで、皆さん実は適正な数独の問題を解くときには、
Sub syokika()
Dim i As Byte, ja As Byte, k As Byte
cn = 0
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
のlst(i, j, k) = k + 1には、
全く意味がなかったことにお気づきだったでしょうか。
2つのcellskaiseki
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 (2014/12/07訂正)
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
で結局最初から、リストを作り直しているからです。
リストを{1,2,3,4,5,6,7,8,9}とする作業は、
全く無意味な作業でした。
では、何故入れてあるのでしょうか。
理由は、2つあります。
数独自動生成ソフトには、2つの方式があります。
1つ目の方式は、すでにこの話において説明した方式です。
もうひとつの方式は、ヒント数0の状態から答えを1つ作り、
空欄を作っていく方式です。
この2番目の方式のときに、
lst(i, j, w) = k + 1で初期化しておく必要があるのです。
第16講最後の課題です。
If mah(y, x) = 0 Then
For i = 0 To mx(y, x) - 1
mah(y, x) = lst(y, x, i)
の部分を
If mah(y, x) = 0 Then
For i = 1 To 9
mah(y, x) = i
と変更するとどうなるか、確認してみて下さい。
つまり、全セル構造解析を使わないとどうなるかという確認作業です。
初心者のためのc++ vc++ c言語 入門 基礎から応用までへ
初心者のための excel 2007 2010 2013 vba マクロ 入門 基礎から応用まで
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
vb講義トップへ
VB講義基礎へ
専門用語なしのC++入門へ
専門用語なしのJava入門へ
専門用語なしのVBA入門
数独のページ
魔方陣のページ
数学研究室に戻る
本サイトトップへ