15パズルの最短手数の最大値ってどうなっているんだろう?とふと疑問に思い調べてみると、「任意の可能な配置へ80手以内で変形でき、80手が必要な配置は確認されている」(Wikipediaより)とのこと。

15パズルは空白を利用して15個のピースを移動させて順番に並べるパズルですが、空白部分を16番ピースをみなすと16個のピースを全部で並び方は16!(1×2×…×16)とおりあることになります。ただしパズルとして成立するのはその半分だけです。なので考えられるピースの配置は 16! / 2 とおりです。これは10^13よりも大きな数で全列挙することはできません。

そこで今回は妥協して3×3の8パズルを考えます。これだと 9! / 2 = 181440とおりなので全探索することができます。

幅優先探索で最短手数の最大値を調べる

幅優先探索をして考えることにします。まず3×3の盤面を二次元配列として考えるのは面倒なので、3行を1つの文字列にまとめてしまうことにします。ピースの番号をそのまま文字にして空白部分を’*’とすると、整列された状態は”12345678*”と表すことができます。

まず空白の上下左右を調べて移動可能であれば移動後の文字列を取得するメソッドを定義します。

幅優先探索で移動できる場合を全部取得します。内部で辞書をふたつ使っていますが、結果を取得するためにこれらをタプルで返します。

定義したメソッドで最短手数が最長になるものを探します。すると31手になるものが2つあることがわかります。

手順を取得する

ついでに手順も取得できるようにします。幅優先探索の処理でfromに格納した情報からひとつ前の状態をしることができるので、逆順にたどって具体的な最短手順を表示させることができるようにします。

最短手順が最長になるものが取得されたらこれを幅優先探索することで整列された状態に戻すための手順を取得し、これを0手目から31手目まで表示させます。