Tukubai、それはシェルスクリプトの使い易さを加速させるコマンド群。
前号では、そのオープン版“Open usp Tukubai”を紹介したが、やり残したことがあった。
豊富なレシピの紹介である。
そこで今号と次号の二回に渡り、Tukubaiの、特に実際のコーディングスタイルが分かり易いレシピを特集する。
「シェルスクリプトとは、僅かなコマンドの追加で、こんなにも応用の効く言語になるのか!」と、あなたはきっと驚くことだろう。
written by USPマガジン編集部
本記事は、USP MAGAZINE vol.5(2012年夏号)掲載記事のWEB再録記事(後半部分)です。
前半はこちら→シェルスクリプトに何でもおまかせ Open USP Tukubaiシンプルレシピ Part1 テキスト編 (前半)
本記事掲載のUSP MAGAZINE vol.5は以下リンク先でご購入できます。
Tukubai はシェルスクリプトをデータベース言語化させるためだけのコマンドセットではないというが、それならもっと一般的な例は無いのか。
数理的な操作の様子が伺えるコードが見てみたい。例えば、何らかの科学技術計算を行っているプログラムであれば、それがわかりやすいと思うのだが。
実際に科学技術計算にも利用しているのだが、そのような例は専門分野の知識から解説しなければならない。
そこでここでは専門分野知識の解説が不要なゲームのレシピを紹介しよう。数学パズル的要素が強いゲームであれば、数理的な操作も見え易いからだ。
■ サンプルプログラム
そこでルービックキューブ(3 × 3 のオーソドックスなもの)を作ってみた。
ルービックキューブは、立方体の一面が一つの行列に対応した6 つの行列であると見なせる。キューブを動かすと、その行列のうちの一つで± 90°回転が発生し、それに伴って隣接する4 つの面に相当する行列の一部要素が、別の行列に移動する。この動きを、シミュレートしようというものである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#!/bin/bash # # 3x3ルービックキューブ # Written by N.Tounaka(xxxxxxx@usp-lab.com) # Date : 5 Jun.2012 # Arranged by USP MAGAZINE(xxx@usp-lab.com) # Date : 6 Jun.2012 # U # 立方体(6面体)の展開図=LFRB # D # F:fore B:back U:up D:down R:right L:left # # 関数f:面Fを時計回り(右90度回転) # 関数F:面Fを反時計回り(左90度回転) # 変数定義(一時ファイルパス/着色データ) tmp=tmp F=`printf '\033[43mF\033[00m'` U=`printf '\033[46mU\033[00m'` R=`printf '\033[41mR\033[00m'` B=`printf '\033[45mB\033[00m'` D=`printf '\033[44mD\033[00m'` L=`printf '\033[42mL\033[00m'` # 関数のインクルード source rubik-cube.func # 初期化/シャッフル/答え作り(シャッフルの逆操作を記録) init rand ${1-=10} 2> $tmp-ans ans=$(tac $tmp-ans | yarr -d | tr a-zA-Z A-Za-z) # ゲームの開始 n=1 while true; do echo " Fore Up Right Back Down Left" echo " ---------------------------------------------" ycat -3 F U R B D L | ycat /dev/null - | sed -e "s/F/$F/g; s/U/$U/g; s/R/$R/g" \ -e "s/B/$B/g; s/D/$D/g; s/L/$L/g" echo "<-f F-> <-u U-> <-r R-> <-b B-> <-d D-> <-l L->" echo -n "${ans}[$n]> " read -n 1 scr echo [ "$scr" = "q" ] && break eval ${scr} 2> /dev/null n=$((n+1)) done rm F B U D R L $tmp-* exit 0 |
リスト3.rubik-cube.func : ルービックキューブプログラム(ファイル2・関数定義)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# RUBIK-CUBE エンジン # # Written by N.Tounaka(xxxxxxx@usp-lab.com) # Date : 5 Jun.2012 # Arranged by USP MAGAZINE(xxx@usp-lab.com) # Date : 6 Jun.2012 init () # 色が揃ったキューブをセットする { for surf in F U B D R L; do yes "$surf" | head -9 | yarr -3 > $surf done } r () # R面(Right)の90度時計回り { self 3 F | cat > $tmp-f self 3 U | tac > $tmp-u self 1 B | cat > $tmp-b self 1 D | tac > $tmp-d delf 3 F | ycat - $tmp-d > $tmp-w; mv $tmp-w F delf 3 U | ycat - $tmp-f > $tmp-w; mv $tmp-w U delf 1 B | ycat $tmp-u - > $tmp-w; mv $tmp-w B delf 1 D | ycat $tmp-b - > $tmp-w; mv $tmp-w D tateyoko R | self 3 2 1 > $tmp-w; mv $tmp-w R } R () # R面(Right)の90度反時計回り { self 3 F | tac > $tmp-f self 3 U | cat > $tmp-u self 1 B | tac > $tmp-b self 1 D | cat > $tmp-d delf 3 F | ycat - $tmp-u > $tmp-w; mv $tmp-w F delf 3 U | ycat - $tmp-b > $tmp-w; mv $tmp-w U delf 1 B | ycat $tmp-d - > $tmp-w; mv $tmp-w B delf 1 D | ycat $tmp-f - > $tmp-w; mv $tmp-w D tateyoko R | tac > $tmp-w; mv $tmp-w R } l () # L面(Left)の90度時計回り { self 1 F | tac > $tmp-f self 1 U | cat > $tmp-u self 3 B | tac > $tmp-b self 3 D | cat > $tmp-d delf 1 F | ycat $tmp-u - > $tmp-w; mv $tmp-w F delf 1 U | ycat $tmp-b - > $tmp-w; mv $tmp-w U delf 3 B | ycat - $tmp-d > $tmp-w; mv $tmp-w B delf 3 D | ycat - $tmp-f > $tmp-w; mv $tmp-w D tateyoko L | self 3 2 1 > $tmp-w; mv $tmp-w L } L () # L面(Left)の90度反時計回り { self 1 F | cat > $tmp-f self 1 U | tac > $tmp-u self 3 B | cat > $tmp-b self 3 D | tac > $tmp-d delf 1 F | ycat $tmp-d - > $tmp-w; mv $tmp-w F delf 1 U | ycat $tmp-f - > $tmp-w; mv $tmp-w U delf 3 B | ycat - $tmp-u > $tmp-w; mv $tmp-w B delf 3 D | ycat - $tmp-b > $tmp-w; mv $tmp-w D tateyoko L | tac > $tmp-w; mv $tmp-w L } f () # F面(Front)の90度時計回り { tail -1 U | tarr > $tmp-u self 1 R | yarr > $tmp-r tail -1 D | tarr | tac > $tmp-d self 3 L | yarr | self 3 2 1 > $tmp-l ctail -1 U | cat - $tmp-l > $tmp-w; mv $tmp-w U delf 1 R | ycat $tmp-u - > $tmp-w; mv $tmp-w R ctail -1 D | cat - $tmp-r > $tmp-w; mv $tmp-w D delf 3 L | ycat - $tmp-d > $tmp-w; mv $tmp-w L tateyoko F | self 3 2 1 > $tmp-w; mv $tmp-w F } F () # F面(Front)の90度反時計回り { tail -1 U | tarr | tac > $tmp-u self 1 R | yarr > $tmp-r tail -1 D | tarr > $tmp-d self 3 L | yarr | self 3 2 1 > $tmp-l ctail -1 U | cat - $tmp-r > $tmp-w; mv $tmp-w U delf 1 R | ycat $tmp-d - > $tmp-w; mv $tmp-w R ctail -1 D | cat - $tmp-l > $tmp-w; mv $tmp-w D delf 3 L | ycat - $tmp-u > $tmp-w; mv $tmp-w L tateyoko F | tac > $tmp-w; mv $tmp-w F } b () # B面(Back)の90度時計回り { head -1 U | tarr | tac > $tmp-u self 1 L | yarr | self 3 2 1 > $tmp-l head -1 D | tarr > $tmp-d self 3 R | yarr > $tmp-r tail -n +2 U | cat $tmp-r - > $tmp-w; mv $tmp-w U delf 1 L | ycat $tmp-u - > $tmp-w; mv $tmp-w L tail -n +2 D | cat $tmp-l - > $tmp-w; mv $tmp-w D delf 3 R | ycat - $tmp-d > $tmp-w; mv $tmp-w R tateyoko B | self 3 2 1 > $tmp-w; mv $tmp-w B } B () # B面(Back)の90度反時計回り { head -1 U | tarr > $tmp-u self 1 L | yarr | self 3 2 1 > $tmp-l head -1 D | tarr | tac > $tmp-d self 3 R | yarr > $tmp-r tail -n +2 U | cat $tmp-l - > $tmp-w; mv $tmp-w U delf 1 L | ycat $tmp-d - > $tmp-w; mv $tmp-w L tail -n +2 D | cat $tmp-r - > $tmp-w; mv $tmp-w D delf 3 R | ycat - $tmp-u > $tmp-w; mv $tmp-w R tateyoko B | tac > $tmp-w; mv $tmp-w B } u () # U面(under)の90度時計回り { head -1 R > $tmp-r head -1 F > $tmp-f head -1 L > $tmp-l head -1 B > $tmp-b tail -n +2 R | cat $tmp-b - > $tmp-w; mv $tmp-w R tail -n +2 F | cat $tmp-r - > $tmp-w; mv $tmp-w F tail -n +2 L | cat $tmp-f - > $tmp-w; mv $tmp-w L tail -n +2 B | cat $tmp-l - > $tmp-w; mv $tmp-w B tateyoko U | self 3 2 1 > $tmp-w; mv $tmp-w U } U () # U面(under)の90度反時計回り { head -1 R > $tmp-r head -1 F > $tmp-f head -1 L > $tmp-l head -1 B > $tmp-b tail -n +2 R | cat $tmp-f - > $tmp-w; mv $tmp-w R tail -n +2 F | cat $tmp-l - > $tmp-w; mv $tmp-w F tail -n +2 L | cat $tmp-b - > $tmp-w; mv $tmp-w L tail -n +2 B | cat $tmp-r - > $tmp-w; mv $tmp-w B tateyoko U | tac > $tmp-w; mv $tmp-w U } d () # D面(down)の90度時計回り { tail -1 R > $tmp-r tail -1 F > $tmp-f tail -1 L > $tmp-l tail -1 B > $tmp-b ctail -1 R | cat - $tmp-f > $tmp-w; mv $tmp-w R ctail -1 F | cat - $tmp-l > $tmp-w; mv $tmp-w F ctail -1 L | cat - $tmp-b > $tmp-w; mv $tmp-w L ctail -1 B | cat - $tmp-r > $tmp-w; mv $tmp-w B tateyoko D | self 3 2 1 > $tmp-w; mv $tmp-w D } D () # D面(down)の90度反時計回り { tail -1 R > $tmp-r tail -1 F > $tmp-f tail -1 L > $tmp-l tail -1 B > $tmp-b ctail -1 R | cat - $tmp-b > $tmp-w; mv $tmp-w R ctail -1 F | cat - $tmp-r > $tmp-w; mv $tmp-w F ctail -1 L | cat - $tmp-f > $tmp-w; mv $tmp-w L ctail -1 B | cat - $tmp-l > $tmp-w; mv $tmp-w B tateyoko D | tac > $tmp-w; mv $tmp-w D } # ランダムに指定回数キューブを回転させる rand () { func=(f F b B u U d D r R l L) for((i=0; i<$1; i++)); do proc=${func[$((${RANDOM}%12))]} echo $proc 1>&2 # 手続きを保存する eval $proc # 関数の実行 done } |