2015年4月25日土曜日

ブロックパズルの解法

ご無沙汰です。
色々あって技術的な研究から離れていましたが、
一旦落ち着きましたので戻ってまいりました。

リハビリを兼ねて久々にLimboを触りました。

たまたまガチャガチャで木のパズルを手に入れました。
下記のように、完成形は3x3x3の立方体になります。
ばらすとひとつづきの木のブロックになりますが、中にゴムひもが通っていて、回すことができます。2または3ブロックおきに曲がり角があります。



手で少しいじってみましたが、すぐに諦め、計算機で解法を求めることにしました。
(手でやるのも面白そうです。意外と色がヒントになりそうです)

3または2このブロックがつながっていて、関節で必ずどちらかの方向にカーブしなければなりません。すべての関節でカーブした結果、立方体に収まっていればOKとなります。
データ構造は意外と単純で、
連続ブロック数 x 節の数
で表されてしまいます。
ブロックの色は考慮しません。
曲がる方向は上下左右の4通り。これが関節数分の組み合わせが発生します。
関節数はこのパズルでは16あったので、4 ^ 16  の組み合わせになります。
40億通りくらい?
(こんなの手で解けるのでしょうか。)

※コードは割愛

ループを単純に回して、総当りさせてみました。
環境はi5 のCPUのWindowsノートパソコン上のACME-SACです。

解かせてみると試した環境では総当りに10時間くらいかかりそうです。
一晩動かしたら気づけば解けていました。(バグによりやりなおして3晩ほどかかりましたが、、、)
検算として実際のパズルに結果を適用すると完成!当たり前とはいえちょっとうれしい。

パフォーマンスですが、ACME-SACの環境(ほぼWindows上のemuと同じでしょうね)では1または2コアをだいたい専有し、全体の2,30%を使うようでした。
シーケンシャルに試していましたが、並行にするだけで結構早くなりそうな予感です。

ただ、それでもすべてのコアを使えないかもしれません。
その場合はemuを複数立ち上げ、分散してやるとフルに活用できるのではないかと
期待しています。

今回はそこまでは手が回りませんでしたが、久々のLimboは楽しかったです。
グリッド試そうかな。
 Goもやらないとな、、、

さて、このパズルプログラミングの題材としては結構適していると思いました。
ループを使ったり、多次元配列をつかったり、言語の機能が色々と試せます。
各試行は独立しているので並行処理もさせやすいです。
新人研修のネタにいいかも。