Home
パズル問題自動生成時代
ナンプレ
はじめに
プログラムで問題を解く
プログラムで問題を自動生成
- 手作りの方法
- 破綻の判定が欲しい
- 序盤の数字のばらまき方
- 多重解にならないために
- 中盤は統計的にごまかそう
- 終盤へのつなぎ方
- 良い問題を目指して
- 終盤は問題の選択
- 見かけが大切
- 隠れた工夫
- 面白さの実現について
- 自動生成プログラムのススメ
乱数の乱用だけでは限界
将来展望
- もしミリ秒で問題生成できたら
- 誰でも簡単に問題が作れたら
- 自動生成も多種多様
- 解き方を見て問題を提供
- パズル作家風の問題生成
- 自動生成プログラムの自動生成
- 多種パズルに適用可能な汎用的アルゴリズム
- いつごろ実現できるか (1)
- オープンソースでの公開
- パズル作家は何をすべきか
パズル問題自動生成時代 -- ナンプレ -- プログラムで問題を自動生成
面白さの実現について
人間のように解いて評価する
プログラムで作っている問題、とくに欧米における問題の難易度を見ると、 プログラムにとっての難易度になっていて、人間が解いた場合のことを 考えていないのではないかと思える場合が実に多い。
パズルは人間が解いて楽しむためにある。
これを忘れたら、パズルでも何でもない。
コンピュータにとって、あるいはパズルプログラミングにとって、 ナンプレの問題を解くプログラムを作ることは最初の一歩に過ぎない。
それに、あまりにも高速に解けるので、実際ちっとも面白くない。
それよりも、なんとかして、人間ならどのように解くのだろうか、 人は解いているとき、どういうことに感動し、 どういうことに気だるくなるのかを判定したいものだ。
そのためには、何としても、人間みたいに解く能力をもった プログラム(人間的ソルバー)を必要とする。
直前の手
プログラムの場合、全てのマスを順番に調べて行くのが普通であろう。 あるマスにある数字が入ることが決まっても、 その数字を決めたら、ちょと解き進んだ盤面に対して 端から順に調べることを普通はやってしまうだろう。
人間はけっしてそんな、死ぬ程緻密な調べ方はしない。
何かが決まれば、それの影響で決まりそうなことを芋づる式に調べようとする。 ある手が決まると、次に決まる個所が複数個所になることがあるが、 人間は一方を追いかけ、他方を忘れるものだ。
なのに、プログラマの中には、そんなことは再帰処理をすれば完璧だと 思いこんでいる者がいる。解くだけならそれでも良いが、
人間的に解こうとすると、 正しく馬鹿な動きをするプログラムを作らないといけない。
一番良い例が、ある数字が決まれば、その数字についてのみあれこれ調べようとする。 盤面の状態が決まれば、その次に決めるのはどこでも良いはずだが、 人間の場合、直前の決定に大きく影響される。 要するに、直前の手が影響する。
プログラムで、正しく馬鹿な動きをするには、 たとえば、
直前に決まった数字を1つだけ憶えておき、 できるだけその数字を決めるように動く
のが有効だ。
たったこれだけで、ずいぶん人間的な解き方をする。
見逃しやすさ
プログラム的には難易度が同じ、つまり同じ処理しかしていなくても、 人間にとってはおおいに難易度が個となって見えたり、 そんな手筋が隠れているのか分からない場合がある。
次の2つの盤面は、いずれも緑色のマスの数字を決定できる。
さて、この2つを比較した場合、どちらが難しいだろうか。 あるいは、どちらを見つけ難いだろうか?
それぞれが決定する理由は、人間に対しては次のように示すのが普通である。
最初の方は、次のように説明できる。
左の黄緑のブロックに注目しよう。 すると、そのブロック外にある4つの4によって、 ピンクの線が通るマスには4が入らない。
従って、左の黄緑のブロック内で4が入るマスは1個所しかないので、 そのマスが4になる。
戦略:3×3のブロックに注目し、縦と横を見る
では、もう1つの問題をみてみよう。
今度は、横9マスが並んだ黄緑になった個所に注目しよう。 すると、黄緑になった空白マスに入れられない数字に注目するのだが、 3に注目すると、ピンクの線が通るマスには3は入れられない。
従って、黄緑のマスで3が入れられるのは、 右端のマスのみである。
戦略:横の9マスに注目し、縦方向を見る
この2つは、人間にとっては随分違う感覚であろう。
そして、難易度、見逃しやすさなどを考えると、 前者の方が易しく、後者の方が難しく、あるいは見逃しやすいのではないだろうか。
プログラム的に見ると
プログラム的に見た場合、この2つは、どのくらいの違いがあるだろうか。
それに、そもそも、プログラムは、ここの説明に従って動作するように 作ったりするだろうか。
たとえば、前者の場合、3×3のブロックについて調べるところまで 到達したとしよう。 その時点で、上下左右にどんな数字が存在するかを調べて、 3×3のブロック内に入れられるマスが1つしかない数字を調べたりするだろうか。
まあ、そういうプログラムも作れない訳ではないが、 そんな作り方はまず誰もしないだろう(と思う)。
普通なら、あるマスに数字(たとえば、1)を入れると決めたとき、 そのマスにその数字を入れたことにより、その数字(1)を入れられなくなった マス全体(縦、横、同一ブロックの他のマス)に、もうその数字は入れられない という情報を書き込むはずだ。
通常、各マスに対して、入れられる数字の候補(1〜9)に対して、 まだ入れられる可能性があるかどうかのフラグを用意する。 そして、マスの数字が決まる度に、ルール上影響するマスの全てについて、 その数字を候補から落とすはずである。
この考え方に従ってしまうと、2つの問題は、ほとんど差がない。
前者は、3×3ブロックに含まれる9マスについて、 候補が1マスにしか存在しない(そのマスにしか入れられない)数字を見つける ことである。
後者は、横9マスについて、同様に、 候補が1マスにしか存在しない(そのマスにしか入れられない)数字を見つける ことである。
プログラム的には、何等差がないので、 まったく同じ部分で処理できる。
要するに、人間にとっては違うと思うことが、 プログラムではまったく同じになってしまうことが発生する。
プログラムの処理を、そのまま難易度評価に反映してしまうと、 どちらも同じになってしまうので、こういう部分もちゃんと 評価しないと、人間にとっての感覚と違ってくる。

