見出し画像

4万6656通り、ふたたび

数独で、ある数字だけ取り出してみてその置かれた場所だけに注目したとき、どういう置き方が可能で何通りあるのか。
先日それを数えてみて4万6656通りだろうと、ひとまず結論した。

そのときに使ったプログラムは、結果を出すのに10分弱かかっていた。

まず行の置き方で可能なものを列挙する(ビットマップを使って圧縮したけれど、これだけで1ギガもの領域を浪費する)。
次に列の置き方で可能なものを列挙するのだけれど、このときは先に列挙した行の置き方の中に存在するパターンだけを残す。
最後にブロックの置き方で可能なものを列挙する。ここでは行と列のパターンで残っているものと一致するものだけを残す。

そういうやり方。

これに関して僕はこう書き残している。

ソルバーを作るのもしたいんだけれど、最初のテンプレートを作成する部分をもっと最適化できるアイデアがあって、そちらも気にかかっている。

結局、こちらを優先してしまった。

圧倒的な速度(0.4秒を切った)で4万6656通りの置き方を列挙してくれる。(不必要に分裂症気味なコードを書いてしまった)

利用している制約条件は同じ。ただし行の可能性をつくるときに、新たな置き場所が列とブロックの置き場所に抵触しないかを確認し、抵触したら探索を打ち切るようにした。(至極オーソドックスな最適化)

行と列とブロックと、それぞれ9つの領域それぞれにただ一つずつ、数字を置かなければならない。これが数独の条件。
新しい置き場所を考えるとき、すでに数字が置かれた領域を侵犯してはならない。そう読み替えることができる。

つまり行制約から行同士の領域侵犯をしない可能性を探索するのだけれど、次の行領域内で可能な置き場所を取り出し、既存の置き場所とペアをつくって、これらのペアが列、あるいはブロックの同一領域に「含まれない」ことを確認する。(含まれたら領域侵犯でアウト)

* * *

先週は売り切れだったけれど、今日は大丈夫だった。ハグジードーナツ。

ゴールデンサークル。(007と、店舗メニューには書かれていた)
パイナップルの輪切りのせドーナツ。

* * *

夕飯は手羽元のコンフィ。


この記事が気に入ったらサポートをしてみませんか?