2009年8月18日火曜日

(37) 大型数独への展開 (16×16 数独)

 先に購入した雑誌「ナンプレ・ファン」には、9×9 の数独(ノーマルナンプレと呼ぼう)の他に拡張したナンプレ(16×16 や 25×25 )問題が掲載されている。SUDOKU_Ver19 では、16×16 ナンプレ専用のプログラムを考えてみた。

 コンピュータ・ソフトの特徴は、大規模化にもかかわらず、正確さと計算時間が人間の能力をはるかに上回るその馬鹿さ加減にある。アルゴリズムは同じなのだから、簡単に大規模化には対応できるものであると考えてやってみた。

 実際には、簡単に拡張ソフトにはすることができたが、そのソフト自体の設計およびアルゴリズムの特徴により細かいところで、いくつかの変更を必要とした。これは、最初からこういう事態を想定していなかったための問題に起因するもので、アルゴリズムが違えばもっと手数は掛からないのかもしれない。

 (1) 計算はSheet 1 の A画面 とのやり取りから始まる。A画面の拡張により、candy_table の表示部分を移す必要があった。
 (2) 問題の入力(Sheet 3)におけるセルの調整。
 (3) 解答の表示場所を新たに確保すること。 などである。
 (4) 探索マクロは、1から9 を 1から Z に変更し、Z=16 をSheet 1 のインプットで与える。これで、Z=25 にも対応できる。今回の拡張では、さらに大規模のものまで対応できるように考慮した。
 (5) 特に、Aサーチの new_class_search では変更箇所が多く面倒であった。
 (6) 当然、group_search や iblock_search なども範囲の拡大をおこなった。

 今回の拡張で、セルの番地 ( i , j ) の取り出しで新しいマクロ row_column_number を作成した。このマクロを使えば、81×81 ナンプレまで対応できる。つまり、9×9 は一桁で済んだが、二桁になるとちょっと取り出すのに工夫がいるので、その簡単なマクロを下に示そう。

 Sub row_column_number()
If Len(cc) = 5 Then
aa = Int(Val(Mid(cc, 2, 1))) : bb = Int(Val(Mid(cc, 4, 1)))
ElseIf Len(cc) = 6 Then
   If Mid(cc, 3, 1) = "," Then
 aa = Int(Val(Mid(cc, 2, 1))) : bb = Int(Val(Mid(cc, 4, 2)))
   ElseIf Mid(cc, 4, 1) = "," Then
 aa = Int(Val(Mid(cc, 2, 2))) : bb = Int(Val(Mid(cc, 5, 1)))
 End If ElseIf Len(cc) = 7 Then
 aa = Int(Val(Mid(cc, 2, 2))): bb = Int(Val(Mid(cc, 5, 2)))
Else MsgBox ("Banchi is mismatching!")
End If
End Sub

 番地から、行・列番号が必要なときには、次のように使う。
  row_column_number
i=aa : j=bb

100×100 ナンプレにも同じようなマクロが作れるが、まだ試してはいない。
49×49ナンプレはその後問題があったので、解いてみたがインプットに時間が掛かる割には簡単にとけた。一般に大規模ナンプレはPサーチだけで解ける簡単な(コンピュータには)問題が多いようだ。人間には手に負えないというか忍耐力だけを試すことになってしまうためなのか。

0 件のコメント:

コメントを投稿