Sugarという制約ソルバーがあります。以下略。前提や使用ツールは前回記事を参考にしてください。
前回記事では、初期条件をマトリックスに展開すれば、最後まで解ける推理パズルを扱いました。今回は、要素に数値項を含む推理パズルを解いてみようと思います。
例題は以下。この例題はフィクションであり、実在のアニメ漫画等の作品、天候使い、食欲とは一切関係ありません。
以下の条件から、天候使いの名前と扱う天候と、食べたワッフルの個数を当てて下さい。
・ソルトは風使いではない
・ソルトと風使いの食べた数を合計すると、ジンジャーの食べた数と同じ
・シュガーの食べた数は、風使いよりも太陽使いよりも多いが、最大ではない
・ターメリックは雲使い
・ペッパーはターメリックより多く食べた
・太陽使いが食べた数は3個以下
・雨使いの食べた数は偶数個
(画像が見にくい場合も考慮してワッフルの個数の項目をここに書きます。1,2,4,5,6です)
さて。
『個々の』ヒントから判る情報をマトリックスに記入してみます。以下のようになるのではないでしょうか。
「ソルトと風使いの食べた数を合計すると、ジンジャーの食べた数と同じ」なので、「少なくともソルト<ジンジャー」→「ソルトの食べた数は6個ではない」というあたりも記入しています。このへん、どの程度直接導かれるかは、意見の分かれる部分もあるかと思います。
さて、今度はマトリックスに記載された○×情報から、解けるところまで解いてみます。クリックしたい人は「自動解答」をクリックしても良いかと思います。
新しく付いた○×から、「ソルトと風使いの食べた数を合計すると、ジンジャーの食べた数と同じ」は「ソルトとペッパーの食べた数を合計すると、ジンジャーの食べた数と同じで6個」と変換できます。
残りの数値を考慮すると、ソルト+ペッパー=2+4or1+5です。
また、ペッパーは太陽使いなので、条件から、シュガーより食べた数が少なくなければなりません。よって、ソルト=2、ペッパー=4となります。ここまでくれば後は道なりに答えを導くことができるでしょう。
この考察が推理パズルの面白いところなのですが、作者としては思わぬ別解が潜んでいたらどうしようと震えてしまうところでもあります。
ではどうしましょう。対策のためsugarの力を借りてみましょう。
例えばですが、sugarに入力するスクリプトは以下のようになります。
;天候使いの名前 (int sugar (1 2 4 5 6)) (int salt (1 2 4 5 6)) (int pepper (1 2 4 5 6)) (int ginger (1 2 4 5 6)) (int turmeric (1 2 4 5 6)) (alldifferent sugar salt pepper ginger turmeric) ;扱う天候の種類 (int sun (1 2 4 5 6)) (int wind (1 2 4 5 6)) (int cloud (1 2 4 5 6)) (int rain (1 2 4 5 6)) (int snow (1 2 4 5 6)) (alldifferent sun wind cloud rain snow) ;ソルトは風使いではない (!= salt wind) ;ソルトと風使いの食べた数を合計すると、ジンジャーの食べた数と同じ (= ginger (+ salt wind)) ;シュガーの食べた数は、風使いよりも太陽使いよりも多いが、最大ではない (< wind sugar) (< sun sugar) (or (< sugar salt) (< sugar pepper) (< sugar ginger) (< sugar turmeric) ) ;ターメリックは雲使い (= turmeric cloud) ;ペッパーはターメリックより多く食べた (< turmeric pepper) ;太陽使いが食べた数は3個以下 (<= sun 3) ;雨使いの食べた数は偶数個 (= 0 (% rain 2))
例題のヒント文(コメントアウト行)と、sugarスクリプト文を併記しています。
ポイントは、前回の記事では、数値を各項目の識別目的にしか使用していませんでしたが、今回の例題では数値項目と他の項目が紐付いていることを利用して、数値項目を識別目的に流用したことにあります。
「最大ではない」の表現が少々泥臭いですが、まあ許容範囲でしょう。
sugarに食わせてみるとちゃんと答えを教えてくれます。
ということで今回は、ひとつの数値項目を含む推理パズルをsugarで解いてみました。
ではふたつ以上あったらどうするの、というのが自然な問いですが、今のところ私はキレイな解を持っていません。力技で解決した記述はいずれ書く予定ですが、上手なアイデアがあればご教示願えればと思います。
それでは今回はこの辺で。