1. はじめに
パズルというものに魅せられ続けた私の人生の中で、最も古い記憶にあるのは、匹見パズルというメーカーが出している「デビルパズル」というものです。
小学校低学年のころ、田舎からの帰りの新幹線の中で、飽きることなくそのパズルに没頭していた記憶があります。
それから30年以上経過した今も、変わらずパズルを趣味にしている。人生とはわからないものです。
前回の記事(【AI駆動開発】パズルのソルバーをAIに「丸投げ」したら、SATソルバーというガチ解法で殴られた話)では、AI(Gemini)とペアプロをして、ナンバーリンクを爆速で解くSATソルバーを作成しましたが、実はこれは今回実践した内容の前座にすぎませんでした。
本当にやりたかったこと、それは パズルの自動生成 。
最近の、生成AIの進歩は目覚ましいものがありますが、しかしパズルの作問という分野においては、まだ全自動でという話はあまり耳にすることはありません。
ひょっとしたらやっているところはやっているのでしょうが、現段階では「自動生成自体を生成AIに丸投げ」しても、おそらくいい結果は返ってはこないでしょう(試していないのでわからないですが)。
であれば、AIに「パズルを自動生成するプログラムの作成」を丸投げしてみたら良いんじゃないか?
そう思って、今回の実践に至ったという経緯がございます。
結果的には、あまり丸投げとはいきませんでした。
さて、昨今AI開発の文脈でよく 「人間は仕様や戦略を決め、AIはコーディング(実装)を行うべき」 という議論を耳にします。
頭では理解していたつもりでしたが、今回の一連の開発を通じて、「あぁ、やはりこれはその通りなのだな」と身をもって実感することになりました。
具体的に実感したことを挙げると、以下の二つに分けられると思います。
- 実装から解放され、エンジニアは戦略に集中できる
- AIに実装させる戦略はエンジニアが厳密に定義するべき
特に二つ目は、当たり前と謡われがちではありました。
しかし今俺はこれを、「言葉」ではなく「心」で理解できた!
今回は、この「巷でよく言われる黄金パターン」を地で行く形で、「ナンバーリンクの自動生成(作問)」 という課題に挑んだ一週間の記録をまとめます。
2. 今回のミッション(作問要件)
前回のソルバー作成も、実はこの作問のための準備でした。目指すゴールは以下の3点です。
- 盤面のすべてのセルを余さず使用すること
- 唯一解であること(別解が存在しない)
- 盤面を縦・横に圧縮できないこと(冗長な直線がないこと)
この要件を満たすアルゴリズムを完成させるまでに、私たちは4つのアプローチを試しました。
そのすべてにおいて、「人間が仮説を立て、AIがコードにする」 というサイクルを高速で回しています。
3. アプローチ1:ランダム数字配置(戦略の敗北)
最初に試したのは、最も直感的で、最も安易な戦略でした。
-
人間の戦略:
「ランダムに数字を置いて、前回作った最強のSATソルバーに投げて判定させればいい。数撃ちゃ当たる作戦」 -
AIの実装:
指定通り、ランダムなペア生成とソルバー判定のループを数秒で実装。
結果:大失敗(生成数ゼロ)
6×6の盤面ですら、1時間回し続けてもまともな問題は生成されませんでした。
【教訓】
AIの実装力がいかに高くても、人間の立てた戦略(アルゴリズム)が三流では結果も三流になるということです。
AIは魔法の杖ではなく、あくまで「優秀な実装者」であることを再認識しました。
4. アプローチ2:ハミルトンパスの活用(視点の転換)
「点を置いてから線を引く」のが無理なら、「線を引いてから点にすればいい」。
そもそも、パズルの作問という古代から連綿と続く娯楽において、「答えから先に作る」などというのは常套手段も常套手段です。
AIにも「そらそうよ」とツッコミをもらったところで戦略を転換したところ、ハミルトンパス という概念をAIから提案されます。
-
人間の戦略:
「全てのマスを通る一筆書き(ハミルトンパス)を先に作り、それを適当に切断して問題にする逆算アプローチで行こう」 -
AIの実装:
「ハミルトンパス生成? お安い御用です」とばかりに、再帰探索アルゴリズムを即座に提示。
結果:6×6なら成功、しかし8×8で爆発
戦略の方向性は正しかったものの、少ないペア数で盤面サイズを上げると「唯一解になる切断パターン」の探索空間が爆発し、計算が終わらなくなりました。
これは、使用する数字の数が減れば減るほど、数字一つ一つが描く線の長さが増えるためです。
ここでもまだ、 戦略の解像度 が足りていませんでした。
5. アプローチ3:2段階アルゴリズム(AI駆動だから選べた「重い」戦略)
ここが最大のブレイクスルーであり、かつ今回実感した「戦略(仕様)は、エンジニアが厳密に定義するべき」内容の一つ目でした。
ここまで作成したアルゴリズムの特徴は以下の二点です。
- 使用する数字の数(ペア数)が少なければ少ないほど、計算量は増える
- 逆に言えば、使用する数字の数が多ければ多いほど、計算量は減る
そこで私は、人間が手作業で実施するには少し面倒すぎる手順 を考案し、AIに実装させました。
-
人間の戦略:
処理を2つのフェーズに分割する。
- Forward Splitting(前進分割):ペア数が増えてもいいから、別解が出るたびにパスを切断し、とにかく爆速で「唯一解」を作る。
- Backward Merging(後退結合):出来上がった多ペア状態から、唯一解を壊さない範囲で少しずつ結合してペアを減らす。
-
AIの実装:
この複雑な状態遷移ロジックを、文句ひとつ言わず正確にコーディング。
結果:劇的な改善
「急がば回れ」戦略は大当たりし、10×10サイズでもサクサク生成できるようになりました。
6. アプローチ4:直角制約の強制(美意識の実装)
生成はできるようになりましたが、出来上がったパズルには、ある問題点が頻出することが明らかになります。
具体的には、「縦横に真っ直ぐ伸びるだけの退屈な線」ばかりの問題しか出力されません。
以下のように縦に圧縮しても問題としての情報量に変化がなく、4×4の大きさの盤面を備えている必要がないのです。

そして、「戦略(仕様)は、エンジニアが厳密に定義するべき」の二つ目の内容として、「パズルとしての美学(要件3)」を満たすための 「追加戦略」 を投入します。
-
人間の戦略:
『全ての行と列において、必ず1回は直角に曲がる(ターンする)』という制約付きで作問すれば、上述したような冗長性は生まれないのではないか(逆に言えば、このような冗長性のある問題はいまだかつて見たことがない)。 -
AIの実装:
ハミルトンパス生成時にこの制約をチェックする処理を追加。人間なら「インデックス計算が面倒くさい……」と投げるような処理も一瞬で完了。
結果:完成
生成される盤面から無駄な直線が消え、線が適度にうねり絡み合う、「人間が作ったような美しいパズル」 が生成されるようになりました。
7. おわりに
ランダム配置から始まり、ハミルトンパス、分割・結合法、そして直角制約。
この一連のアルゴリズム改良を、わずか一週間で駆け抜けられたのは、間違いなく 「人間が戦略を決め、AIが実装する」 という役割分担が機能したからです。
- 人間:パズルの美学、計算量の見積もり、アルゴリズムの選定(Strategy)
- AI:再帰処理、バックトラック、複雑な条件分岐の記述(Implementation)
よく言われることではありますが、この分業により開発スピードは何倍にも跳ね上がりました。
さて、次の課題は「難易度調整」ですが、これがまた非常に難解です。
今回の一連の開発において、「ナンバーリンク作問の必要最低限」を満たすことができるようになりましたが、これはあくまでも最低限。
現段階では、以下のような課題があることが明らかになっています。
- 12×12を超える大きさの盤面のパズル作成には時間がかかる
→ ナンバーリンクという種類のパズルの特性上、盤面の大きさが難易度に直結する - 線が円を描くように問題が生成されてしまう
→ 外側から線を埋めることで容易に解答可能である
すでにいくつかの実装案を考えてはAIに実装させるを繰り返していますが、今のところ芳しい結果は得られていません。
進展ありましたら、また記事にしようと思います。
以下、簡単ではありますが生成した問題をいくつか挙げておきますので、休息のお手慰みにどうぞ。
GitHubリポジトリ(記事作成時点コミット):
https://github.com/mashinosatoshi/pencil_puzzle_solver/tree/df30520bbca60dd6e7a164a9eb90cefc09a452ce/numlin
※記事も一部Geminiを使用して作成しています。
