8. 立体ペントミノ |
ペントミノをPICで解くことで遊んでいたら色々と思いつき、立体ペントミノ(3D pentomino / Solid Pentomino)に挑戦してみた。立体ペントミノは、ココの右下ある写真がそれで、5個の立方体を平面上で貼り合わせてできる12種のピースで直方体を作るもの。1×6×10、2×5×6、3×4×5の直方体ができる。詳しくはウィキペディア参照。
今回、立体ペントミノを解くことはそこそこにして、解を立体表示することに注力。しかしあまり期待通りに表示できなかった。
デジカメで撮影しているのと、カメラとの同期がとれないためかイマイチ。
求解ソフト
かなり前に立体ペントミノを試しませんかとのメールを頂き、挑戦したのですが当時はピース定義をミスっていて、全解が正しく求められませんでした。今回、再挑戦。解を求めるソフトはPC(Windows)で動かします。
3×4×5の解を求めるプログラムは下記です。あまり速くなく、また立体の回転による重複解の排除の対策が十分できていません。簡単にできる I ピースの範囲を限定し、全解(3,940)の4倍の解数(15,760解)を求めるのに13分30秒程度(Pentium4 2.4GHz)かかります。重複解の排除のために、Fピースの向きを限定したり色々試したが上手くいかず、このへんで妥協。
ちなみに、2×3×10の解数(12)の8倍の解(96解)は2秒ちょっと、2×5×6の解数(264)の8倍の解(2112)は170秒ほどで求まった。
解は下記ようなテキストで出力されます。
+---+---+---+---+ | I | L | T | f | +---+---+---+ + | U | f f f | + +---+ +---+ | U | V | f | Z | +---+---+---+---+ +---+---+---+---+ | I | L | T | Z | +---+---+ + + | W W | T | Z | +---+---+ + + | U | V | T | Z | +---+---+---+---+ +---+---+---+---+ | I | L | T | Z | +---+---+---+---+ | U | W W | X | + +---+---+---+ | U | V V V | +---+---+---+---+ +---+---+---+---+ | I | L L | X | +---+---+---+ + | P P | W | X | + +---+ + | P P P | X | +---+---+---+---+ +---+---+---+---+ | I | N N N | +---+ +---+---+ | N N | y | X | +---+---+ +---+ | y y y y | +---+---+---+---+
- プログラム・ソース Borland C++ Compiler 5.5 (コンパイルオプション -O2 -5)で807秒 (Pentium4 2.4GHz)
- 15,760解のデータ(ZIP圧縮ファイル956KB)
(注)プログラム、解データにはバグがあるかもしれません。無保証です。
ハード(メカ)
フレームはアルミチャンネルとアルミ板で作成。動力源はマブチモータで、モータの回転運動をタミヤのプーリで減速し、スライダクランク機構で直線運動にする。
直線運動するアルミ板に3×4のLEDアレイを取り付け、前後に動かすことで立体を表示する。
組み立てには2ミリの皿ビスを利用。久しぶりにタップを立てた。ホームセンタで購入したビスはナットとセットだったのでナットばかり余った。
ハード(エレキ)
表示制御にはPIC16F648Aを使い、解データは取りあえずアセンブラのソースコードに埋め込む。回路的には外部からの解データ供給も考慮して、ポートを開けておいたがたぶんやらない。
使ったLEDは以下のような四角いもの。透明樹脂でパッケージされていて中心はレンズになっている。ヤスリでレンズを削り、表面にキズを付けて面で発光するようにした。右下写真が加工前後、右側LEDが加工後。しかし、まだ中心のレンズ跡が明るすぎた。
LEDを取り付けた表示部と、PICが載る基板との間は、壊れたプリンタヘッドのフラットケーブル(左下写真)を再利用した。ピッチが狭く、熱に弱いのでハンダ付けが大変。今回の工作で一番大変だったのがこのハンダ付け。
表示部は青色LED 12個(3×4)、この表示面が前後に奥行き5個分動くことで60個のセルを表示できる(はず)。右下写真はPICの載った基板、PICの他にACアダプタコネクタ、電源スイッチ、レギュレータIC(PIC用、モータ用)、電流制限抵抗などが載る。
表示ソフト
表示ソフトは、PICのタイマ割り込みを利用して、12個のLED表示面を奥行き方向に5面分(往復で10面分)のダイナミック表示する。表示部の往復時間をフォトインタラプタを使って測定し、それを1/10にすることで片道1面の表示時間を求める。その表示時間毎に表示面を切り替えて表示する。
色々試して汚いソースになったのと、公開しても参考にならないと思うので、プログラムソースは省略。
Copyright (C) Nakamura 2008 |