ヒントの位置が指定された ナンプレの高速な生成法

Download Report

Transcript ヒントの位置が指定された ナンプレの高速な生成法

パズル問題自動生成時代
株式会社タイムインターメディア
知識工学センターパズル推進室
稲葉 直貴
発表内容について
 様々な種類のパズルに応用できる汎用的な
問題自動生成アルゴリズムの紹介。
 NumberPlace,CrossSumと呼ばれるパズル
への本アルゴリズムの適用について説明し
それらを通じてより一般的なパズルに対する
問題自動生成アルゴリズム設計手法を提案。
発表の流れ
NumberPlace自動生成アルゴリズムの紹介
他のパズルにも応用できそうな部分を抽出
CrossSumの自動生成アルゴリズムを構築
NumberPlaceとは?
(1)縦横の全ての列に1から9を一つずつ入れる
(2)太線で囲まれた3×3のブロック内にも1から9を一つずつ入れる
●問題●
4
3
★解答★
5
1
2
4
3
6
8
9
5
1
7
9
2
5
4
9
7
1
2
3
5
6
8
4
5
4
7
3
5
6
8
4
1
7
2
9
3
7
3
2
1
4
6
9
5
8
6
8
5
3
9
2
7
4
1
4
1
9
7
5
8
3
6
2
3
1
2
9
9
3
5
6
8
9
1
5
8
2
7
9
6
1
4
3
5
1
5
3
6
1
3
9
5
4
6
5
8
7
2
3
4
8
1
2
7
6
9
5
6
1
7
今回考える問題について
入力:ヒント座標の集合
出力:入力座標に数字が配置された
ユニークな解を持つ問題図
4
3
5
1
9
2
5
4
5
4
7
3
ヒント
3
2
9
5
1
9
3
6
8
9
1
5
1
5
3
6
5
6
1
7
与えられた
ヒント配置で
問題を作成
問題作成の流れ
ヒントの位置を決める
問題作成の流れ
ヒントの位置を決める
解答盤面を作成する
7
4
3
8
6
9
5
1
2
9
6
1
2
3
5
7
8
4
5
8
2
4
1
7
6
9
3
6
3
7
9
2
8
4
5
1
4
1
5
3
7
6
9
2
8
2
9
8
1
5
4
3
6
7
8
7
4
6
9
1
2
3
5
1
3
2
5
9
6
5
7
4
8
3
2
8
1
7
4
6
9
問題作成の流れ
ヒントの位置を決める
解答盤面を作成する
ヒント以外を除去する
7
4
3
8
6
9
5
1
2
9
6
1
2
3
5
7
8
4
5
8
2
4
1
7
6
9
3
6
3
7
9
2
8
4
5
1
4
1
5
3
7
6
9
2
8
2
9
8
1
5
4
3
6
7
8
7
4
6
9
1
2
3
5
1
3
2
5
9
6
5
7
4
8
3
2
8
1
7
4
6
9
これで唯一解になっていれば完成!
問題作成の流れ
このヒントで解いてみる
7
4
3
5
1
2
9
1
2
3
5
4
5
2
4
1
7
3
3
7
1
5
9
8
5
6
1
1
3
5
3
6
5
3
6
3
8
5
4
3
5
6
1
4
空きマスの数:37
問題作成の流れ
このヒントで解いてみる
7
4
3
5
1
2
9
1
2
3
5
4
5
2
4
1
7
3
3
7
1
9
5
3
1
9
8
ヒント数字を変更する
4
1
5
3
8
6
1
1
3
5
3
5
6
5
6
3
5
6
1
4
空きマスの数:37→35
★この操作を繰り返して全マスが確定する状態にする
タネとなる初期解答図の生成
まず一つのパターンを用意
7
4
3
8
6
9
5
1
2
9
6
1
2
3
5
7
8
4
5
8
2
4
1
7
6
9
3
6
3
7
9
2
8
4
5
1
4
1
5
3
7
6
9
2
8
2
9
8
1
5
4
3
6
7
8
7
4
6
9
1
2
3
5
1
3
2
5
9
6
5
7
4
8
3
2
8
1
7
4
6
9
解答パターンの生成
同じブロック内の列を
ランダムに選ぶ
まず一つのパターンを用意
解答盤面の性質を壊さず
数字をシャッフルする
7
3
4
3
7
8
6
9
5
1
2
9
6
1
2
3
5
7
8
4
5
8
2
4
1
7
6
9
3
6
7
3
7
6
9
2
8
4
5
1
4
1
5
3
7
6
9
2
8
2
9
8
1
5
4
3
6
7
8
7
4
6
9
1
2
3
5
1
3
6
2
5
9
6
3
5
7
4
8
3
2
8
1
7
4
6
9
この処理を全マスに対して行う
解答アルゴリズム(ソルバー)について
★状態が「確定」する箇所だけを埋める
解答処理を高速に行うために…
 解くために用いる「手筋」の制限
(確定する全ての箇所が埋まるわけではない)
 再帰的な手続きを使用
(変化があった箇所だけをチェック)
問題を解く上で扱う要素
数字
候補
盤面の数字
4
6
1
5
2
3
2
1
2
9
9
5
3
8
6
2
5
5
4
2
8
7
6
9
8
4
5
7
5
7
5
3
1
7
9
盤面に入る数字の候補
9
4
3
1
2
3
2
1
8
6
5
7
1
4
6
9
1
2
3
1
2
3
4
5
6
4
5
6
7
8
9
7
8
9
1
2
3
1
2
3
4
5
6
4
5
6
7
8
9
7
8
9
「手筋」について
NumberPlaceの手筋には二種類が存在する
 「数字」を入れる規則
(どういうとき数字を入れられるか)
 「候補」を消す規則
(どういうとき候補が消せるか)
数字を入れる三つの規則
 あるブロックで3が入る候補が一つしか
存在しなければ、そのマスに3が入る
3
X X
X
X X
X
X X
 ある列で6が入る候補が一つしか
存在しなければ、そのマスに6が入る
X
X X X X 6
 あるマスに入る候補が7しかなければ
そのマスに7が入る
1 2 3 4 5
6 7 8 9
7
X X X
候補を消す三つの規則
あるマスに数字5が入るとき
 そのマスから5以外の候補を消す
 同じブロック内から5の候補を消す
 同じ列内から5の候補を消す
5
ここでは以上の規則だけを用いる
(全ての問題を解くには不十分)
用いる手続き
 数字を入れる手続き
位置(x,y)に値zを代入
 候補を消す手続き
位置(x,y)の候補から値zを消去
「数字を入れる手続き」の実行
数字を代入すると、その影響を受ける範囲で
「候補を消す手続き」が直ちに呼び出される
5
(2,4)に5を入れたことにより
赤く図示された範囲に対して
候補を消す手続きが実行される
「候補を消す手続き」の実行
 候補を消すと、その影響を受ける範囲で
新たに数字が確定するかチェックされる
★数字を入れる三つの規則を調べる
数字が確定する場合は再び
「数字を入れる手続き」が呼ばれる
(6,4)から候補5が消されたことで、
青く図示された範囲がチェックされる
5
解答アルゴリズム
数字が一つも入ってない状態から開始し、
既に数字が明かされている全ての箇所で
「数字を入れる手続き」を実行する
盤面の一辺の長さをNとしたとき
「数字を入れる手続き」の実行回数:N^2
「候補を消す手続き」の実行回数:N^3
★全体ではO(N^3)で終了
実行時間:O(N)
実行時間:O(1)
問題生成アルゴリズム(ジェネレータ)
について
 貪欲法に基づいている
「解答後の空きマスの数」が少なくなるよう
問題盤面(ヒントの数字)を変更していく
 生成は確率的
常に成功するとは限らない
ヒント数字の変更手順
 全てのマスを順に見ていく
 ヒント位置であれば1から9まで変更
解答後の空きマス数をチェック
 前より空きマス数が下がれば
そのヒントを残し最初に戻る
下がらない、もしくは「解なし」
ならば数字を元に戻し次へ
 空きマスが0になる(成功)か
最後の数に到達(失敗)したら終了
4
3
5
1
9
2
5
4
5
4
7
3
3
7
4
5
9
8
3
6
8
6
1
5
1
5
3
6
5
6
1
4
変更を効率良く行うために
一箇所のヒントの変更に対し、毎回最初から
解き直すのは効率が悪いので段階を踏む
★この目的のため「局所ソルバー」が使われる
7
7
5
9
2
5
4
9
5
4
7
3
5
3
7
9
5
1
8
4
3
5
8
6
1
1
5
3
3
5
6
5
6
3
1
4
4
3
1
55 1
2
3
5
2
4
4
1
7
3
3
7
9
5 3
8
1
4
1
1
3
5
5
8
6
1
6
1
5
3
3
5
6
5
6
3
5
6
1
4
アルゴリズムの終了
成功した場合
最終的なヒントと解答後の盤面を出力
(成功時には全てのマスに数字が入っている)
 失敗した場合
あるヒント位置に対し唯一解となる問題図が
存在するかどうかを判定するのは困難なので
再チャレンジするか否かは人が判断する
(ヒントの数を増やす、位置を変える 等)
問題作成の流れ (まとめ)
解パターン生成
作成成功 作成失敗
ヒントを代入
空きマス0
解く
もう下がらない
空きマスを数える
減少
ヒントの変更
増加(orイコール)
ヒントを元に戻す
CrossSumとは?
(1) 白マスに1から9のいずれかの数字を入れる
(2) 三角マスの数字はそこから一列に連続している
白マスに入れられる数字の合計を表す
(3) 一列に連続する白マスに同じ数字は入らない
●問題●
4
★解答★
15
4
3
3
16
20
20
12
15
1 2 16
3 8 9
12
5 7
アルゴリズムの入出力
入力 : 三角マス(ヒント)のパターン
出力 : 上のパターンを持つ問題&解答図
入力
出力
4
3
20
15
1 2 16
3 8 9
12
5 7
問題作成の流れ
解パターン生成
作成成功 作成失敗
ヒントを代入
空きマス0
解く
時間切れ
空きマスを数える
減少
ヒントの変更
増加(orイコール)
ヒントを元に戻す
解パターン生成 その1
適当な1から9の順列を用意
7 5 2 3 8 1 9 6 4
この繰り返しで盤面を覆う
9 6 4 7
9 6 4
9 6
9
5
7
4
6
9
2
5
7
4
6
3
2
5
7
4
8
3
2
5
7
1
8
3
2
5
9
1
8
3
2
6
9
1
8
3
4
6
9
1
8
7
4
6
9
1
5
7
4
6
9
2
5
7
4
6
2
5 2
7 5 2
4 7 5 2
…
この上から三角マスをかぶせれば数字の重複は起こらない!
解パターン生成 その2
これだけでは
ランダム度が低い
上下左右を確認して
変更できる箇所を
適当に入れ替える
7
4
6
9
1
8
3
2
5
7
4
5
7
4
6
9
1
8
3
2
5
7
2
5
8
7
4
6
9
1
8
3
2
5
3
2
5
7
4
6
9
1
8
3
2
8
3
2
5
7
4
6
9
1
8
3
1
8
3
2
5
7
4
6
9
1
8
9
1
8
3
2
5
7
4
6
9
1
6
9
1
8
3
2
5
7
4
6
9
4
6
9
1
8
3
2
5
7
4
6
7
4
6
9
1
8
3
2
5
7
4
5
7
4
6
9
1
8
3
2
5
7
ヒントの代入
解答から一意に
ヒントが定まるので
それを代入する
8 1 9 276 4
7 5 262 3
7
9
20
3
24
19
6
4 187 8 6 5 8 111 3 1 2
22
29
6 8 7 3 4 213 6 9 2 5
14
23
13
9 9 5 237 3 9 5 6 111 8
20
18
1 1 4 2 8 3 242 5 2 9
6
17
8 1 2 4 254 2 6 4 5 198
26
4
3 8
1 9 2 7 8 165 1 3
26
8
21
23
2 1 5 8 7 116 7 8 3 1
11
14
13
5 5 6 168 4 6 3 1 127 6
26
18
7 2 7 9 3 5 9 4 7 5
24
12
4 7 8 7 9 8 1 3 5 4
5
7
16
7
5
4
1
8
13
4
7
2
7
問題作成の流れ
解パターン生成
作成成功 作成失敗
ヒントを代入
空きマス0
解く
時間切れ
空きマスを数える
減少
ヒントの変更
増加(orイコール)
ヒントを元に戻す
CrossSumソルバーの構成
★3つの要素が互いに関係し合っている
盤面に入る数字
数字
その列に入る
数字の組み合わせ
盤面に入る
数字の候補
候補
ヒント
数字が入った場合の処理
可能な組の更新
4
{389}
{479}
{569}
{578}
その列から3の候補を消す
15
3
16
20
3
12
そのマスから他の候補を消す
候補が消された場合の処理
可能な組の更新1
マスで候補が一つなら入れる
※仮に列から3の候補が消えたら
3を含む組を消す
4
3
可能な組の更新2
※仮にマスからある組の候補が
全て消されたらその組を消す
3
15
16
20
12
列で候補が一箇所なら入れる
可能な組が更新された場合の処理
{159}
{168}
{249}
{258}
{267}
入らない候補を消す
※3,4,6,7は入らない
4
15
3
16
20
12
※5は必ず入る
入る数の候補が一箇所なら入れる
解答アルゴリズム
全ヒントに対し可能な数字の組み合わせの更新を行う
4
15
3
16
20
12
★最終的な結果は更新の適用順序にはよらない
問題作成の流れ
解パターン生成
作成成功 作成失敗
ヒントを代入
空きマス0
解く
時間切れ
空きマスを数える
減少
ヒントの変更
増加(orイコール)
ヒントを元に戻す
ヒントの変更
背景にある解を介してヒントを変更してやる
4
3
12
4
12
1 2
3
3
12
13
全部埋まらない
12
7
12
1 2 12
3 4 5
13
8
1
6 7
「解」を変更
★少なくとも一つ解の存在が保証される
変更手順(例)
※左上のマスから順次数字を入れ替えていく。
4
3
12
12
1 2 12
3 4 5
13
6 7
※数字の変更は同時に
一箇所にのみ行われる。
入れ換えた結果space(解答後の空きマス数)が
下がったら、その数を残し、再び左上に戻る。
全てのマスが埋まる(成功)か、どの数字を変更しても
spaceが下がらず右下に到達(失敗)したら実行終了。
失敗後の処理
ナンプレでは失敗した盤面を捨ててやり直していたが‥
7 5 262 133 208 1 9 326 144 307
24
4 777
4
8 161 9 8 7
18
32
6 1
9
3 9 7 6 8
20
13
29
13
9 4 9 237
7 8 301 9
21
32
1 2
2 5 9 6
11
14
12
8 1
4
3 6 218
16
11
14
3 168 111
5 8 6
18
10
17
2 4
6
7 1
17
12
19
4
5 9 3 178 4 9
3
7
17
23
26
3
9
8
9
7
19
19
4 7 5 8 6 8 1
5
77
2
4
1
1
8
7
1
7
問題点:盤面が大きくなると
面積に対して指数関数的に
成功確率が低下する。
問題作成の流れ (改良版)
解パターン生成
盤面の再生処理
ヒントを代入
作成成功 作成失敗
空きマス0
解く
時間切れ
空きマスを数える
減少
ヒントの変更
増加(orイコール)
ヒントを元に戻す
新たな解パターン生成
7 5 262 133 208 1 9 326 144 307
24
7
2 4 2
1 8 161 9 8 7
4 77 1
18
32
5 9 6
7 203 9 7 6 8
6 1 2
13
29
13
9 9
5 7 8 301 9
9 4 9 237 5
21
32
7 9
5 7
8 8
1 112 5 9 6
1 2 6
14
12
1 6
4 164 2
7 1
9 3 6 218
8 1 8
11
9 3 1
2 2
6 18514 8 6
3 168 111 5
10
17
1
3
2
2
7
8 4
3 7 1
2 4
6 3
17
12
19
5 9 3 178 4 9 5 1 1774 3
23
26
5 8 9 6
2 9
1 7
4
7 3 2 9 1
19
19
8 8
6 4
9
4 7 5 8 6 8 1 7
5
77
2
4
1
1
8
7
2
4
1
4
3
7
背後にある解に注目
解けなかった部分を除く
ランダムに再配置
これを種に再び問題生成
全てのマスが埋まるまで繰り返す
★完成図★
新たな種から生成される問題は
より唯一解に近づいている
(と期待される)
この操作を問題が完成するか
納得のいくまで繰り返す。
7 5 182 123 258 1 9 326 144 307
24
7
2
1
4 127
4
8 161 9 8 7
29
32
6 9 5 8 7 153 9 7 6 8
29
13
94 1 3 127 9 5 7 8 181 9
21
23
1 2 7 5 8 1 282 5 9 6
5
25
8 1 1 4 254 7 9 3 6 258
12
3 188 111 1 3 2 6 1456 1 5
10
15
2 3 1 2 4 176 5 3 2 1
12
23
5 9 3 178 5 9 8 1 377 6
32
10
7 6 2 9 7 8 9 2 1 4
19
19
4 7 5 8 6 8 1 8 2 9
5
77
2
4
1
1
8
8
4
1
3
7
考えるべきことのまとめ
 初期盤面をどう作るか
 ソルバーの構成
 問題盤面の変更方法
 失敗時の盤面再生処理
初期盤面をどう作るか
 解を保障する状態からのスタートが望ましい
用いるソルバーが完全でないと盤面が矛盾をはらんでも
検出できず、解答不能状態に落ち込む場合がある。
これを回避するためには「※解の存在を保証し」つつ、
問題盤面を変更していく必要がある。
※ナンプレの生成過程はこの条件を満たしていない
(そうすることは可能だが却って遅くなる)
ソルバーの構成を考える
 基本となる要素は何か?
盤面の状態、候補、その他の制約条件など
 それらが変化したとき影響を受ける範囲は?
変化があった箇所だけ再帰的に解くように設計
★局所的な盤面変更を行う今回の手法に有効
 どこまで簡素化するか
解答能力と計算量のトレードオフを考慮
一般に「完全ソルバー」を作るのは困難
問題盤面の変更方法
 解の存在を保証するように変更
解を変更し、それに合わせて問題盤面を変更する
 部分的に解いたものを保存しておく
変更の度に一から解き直すのは非効率的
 唯一解までの「距離」をどう計るか
空きマス、候補数の総和
失敗時の盤面再生処理
 既に「できている」部分を残してシャッフル
どこまでを「できている」と見なすか
壊しすぎる→収束しない
残しすぎる→閉塞状況を打開できない
今後の予定
 いくつかのパズルに対して適用してみる
 各々について難度を制御できるようにする
私事
 もっと仲間を増やす
 パズル界をルール設計中心の方向へ