小さいサイズのスライドパズルを解かせる

この記事は

adventar.org

の9日目がなんか空いていたので書いている記事です。

導入

未来予知者なので、11日の枠にnaanさんの記事が投稿されることを知っています。具体的には「あほくさスライドパズル」と呼ばれる2x3サイズのスライドパズルを手で解くコツがよくまとまっており、naanさんの天才さも確かに感じられる良記事が存在する未来が見えます。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/naan11235813/20211224/20211224032730.png
スライドパズルを解いているところ 。naanさんの記事より

しかし、パズルを速く短く解くのは (naanさん以外の) 人間には至難の業です。 凡人にも簡単な方法としてコンピュータにこのスライドパズルを解かせてみましょう。

解き方

グラフをつくる

このパズルでは適当なピースを1個スライドすることである盤面から他の盤面に変移できます。

f:id:sh-mug:20211225143052p:plain
変移の例

盤面の状態を頂点とみなし、盤面変移の関係を辺とみなしたグラフを考えます。するとスライドパズルの解を求める問題は、このグラフ上で初期盤面から正解盤面までの路を探索する問題に帰着されます!

f:id:sh-mug:20211225154636p:plain
グラフの探索問題に帰着された

盤面の状態数は高々6!=720通りなので、この規模ならBFSで最短路を求めても高速に動作します。

コードを書く

書きます。

書きました。 (クリックで展開されます)

gist.github.com

解く

f:id:sh-mug:20211225171824p:plain
解けるか……?

解きます。

$ time python3 ahokusa.py < ahokusa.in
下左上右右下左上左下

real    0m0.044s
user    0m0.044s
sys     0m0.000s

f:id:sh-mug:20211225171843p:plain
やったー

解けました。やったね

2x3サイズなら簡単な知識だけでソルバーを作れるので、みんなも書いてみよう1

元ネタ記事の作成、およびこの記事の確認をしてくださったnaanさんに最大限の敬意を表し、記事の締めといたします。

おまけ

初期盤面をコピーしスクリプトを実行してSlackに貼り付けるまでの時間でnaanさんが解き終えていました。一生勝てません

f:id:sh-mug:20211225172330p:plain
自分が解答するより

f:id:sh-mug:20211225172403p:plain
naanさんの方が4秒速かった


  1. naanさんにも紹介されている通り「千矢スライドパズル」とよばれる4x3サイズのスライドパズルもありますが、これは盤面数が12!=479001600の規模で存在します。実用的な速度で短い解を求めるにはA*などのヒューリスティクスが必要です。