th0x0472.log

アクセスカウンタ

zoom RSS 「第12回本当は怖くないシェル芸勉強会」に参加してきました

<<   作成日時 : 2014/08/05 00:40   >>

ブログ気持玉 0 / トラックバック 0 / コメント 0

問題と模範解答がこちらで公開されてます

・・・が、しばらくブログ書いてなかったし、せっかくなので自分はこう解いた、ココまで出来た・ココまでしか出来なかった、ってのを晒してみます。


Q1. 次のように、画面にバッテンを描いてください。


$ echo 5 9 | xargs -n 1 | awk '{size=$1; for(i=1;i<=size;i++){for(j=1;j<=size;j++){if(i==j || size-j==i-1){C="x"}else{C=" "}; printf("%s",C)} printf("\n")}}' 
x   x
 x x 
  x  
 x x 
x   x
x       x
 x     x 
  x   x  
   x x   
    x    
   x x   
  x   x  
 x     x 
x       x


awkで完結というよりはむしろ力技ゴリ押しで、シェルの機能やいろんなコマンドを使うのを諦めてるのが悔しいです。最初はサイズ決めうちだったのが気に入らなかったので、パイプで受け取るようにしてみました。そうしたらawkのNRの出番がなくなってしまいましたけど・・・。

awkの最初の size=$1 は必要か?といえば、動作の上ではなくてもいいけど、むしろない方が短いけど、こうした方が分かりやすいと思うのでこうしてます。


Q2. 次のechoの出力から回文を完成させてください。

revというコマンドを教えてもらいました。
が、あえて使わずと言うか上手く使えずに、ひどくbash依存な回答です。


$ echo "たけやぶ\nわたしまけ" | while read s; do echo "${s}$(for i in $(seq $((${#s}-2)) -1 0); do echo -n ${s:$i:1}; done)"; done 
たけやぶやけた
わたしまけましたわ


${#s} で ${s}の長さを得て、${s:POS:LEN} で ${s} の先頭からPOS文字飛ばした位置からLENだけ取り出してます。つまり、「やけた」のために、forを回して最初に「や」を取り出して、次のループで「け」を取り出して・・・ということをしているわけです。


Q3.ウェブ等からデータを取得して南武線の駅名のリストを作ってください。

http://ekikara.jp/newdata/line/1301351.htm をパースしてました。


$ curl -s http://ekikara.jp/newdata/line/1301351.htm | iconv -f cp932 -t utf8 | grep -o 'textBold.*' | sed 's/textBold">//' | cut -d '(' -f 1




Q4. 北から順(正確には都道府県番号順)に並べてください。

こういうこともISOで決まってるんだ〜、ということに驚き。どなたかがISOの番号仰ってたので、その番号でWikipediaを検索してヒットしたページの一覧をパースしてます。


$ curl -s http://ja.wikipedia.org/wiki/ISO_3166-2:JP  | grep "JP-[0-4][0-9]" | sed 's/<[^>]*>//g' | awk '$0=$2' | grep -f pref


最初 pref テキストファイルに空行入ってて、全県ヒットしてしまって残念な別解を出してしまったのはナイショです。


Q5. 各行の数字を大きい順にソートしてください。


$ cat input| while read L ; do echo "$(cut -d " " -f 1 <<<${L}) $(cut -d " " -f 2- <<<${L} | xargs -n 1 | sort -rn | xargs)"; done
A 1234 31 4 -42
B 94 31.1 10 -34


数字を大きい順にソートするなら sort -rn で一発ですが、行頭のA,Bはそのまま出す、という条件付きですので、cutで先頭の文字と数字列挙部分に分割して 、数字列挙部分はxargs -n 1で縦にしてsort -rnしてxargsで1行に戻してます。


Q7. Q6のグラフを次のように縦にしてください。

これが一番難しかった気がします。これもawkゴリ押しなので悔しいです。長くて1回でツイートできないし。


$ cat num | xargs  | awk '{for(j=11;j>0;j--){for(i=1;i<=NF;i++){if(j<=$i){printf(" *")}else{printf("  ")}}printf"\n"}} END{for(i=1;i<=NF;i++){printf("%2d",$i)} printf"\n"}'
          
       *  
       *  
       *  
       *  
       *  
 *     *  
 *   * *  
 * * * *  
 * * * * *
 * * * * *
 5 3 410 2


とりあえずそれらしくはなったけど、数字は2桁まであるんだから1列に3文字割り当てるべきだろ〜というところ、2文字しか割り当ててないあたり、残念な感じです。

高さを決め打ちにしてしまっていて、ホントなら入力された数字を見て決めるべきだろ、と思いつつ、面倒なのでやめました。 本筋じゃないし、と言い訳しつつ力尽きました。

0は対応できるけど、負の数を入力されたら対応できないな−。どう答えるのが正解か、よくわからないですけど。


Q8. 次のデータは、何かの試合の結果ですが、各チームが何勝何敗だったかを集計してください。引き分けは無いと仮定して構いません。

これは時間内に解けませんでした。悔しい。

この回答だと結果にAが登場しないんですね。勝った数を数えてるのに、Aが一勝もしていないので。負けた数も分からない。

で、あとで出した答えがこちら。


$ cat result | tr - ' ' | awk '{T[$1]++;T[$2]++;if($3>$4){W[$1]++}else{W[$2]++}} END{printf("   W  L\n"); for(t in T){printf("%s %2d %2d\n",t,W[t],T[t]-W[t]);}}'
   W  L
A  0  3
B  3  1
C  2  1


T[t]が、チーム(A-C)が結果に登場した回数=試合をした回数で、W[t]がチームの勝利数。よって、T[t]-W[t]が敗北数です。入力の各行でT[t]とW[t]を数えて、ENDで形式整えて出してます。



もう一つ、あえてawkを使わないで挑戦してみましたが、これで限界でした。


$ cat result | sed 's/\-/ /' | while read S ; do T1=$(cut -d' ' -f 1 <<<${S}) ; T2=$(cut -d' ' -f 2 <<<${S}) ; [ $(cut -d' ' -f 3 <<<${S} | bc) -gt 0 ] && printf "%s win\n%s lose\n" ${T1} ${T2}  || printf "%s win\n%s lose\n" ${T2} ${T1}; done | sort | uniq -c  
   3 A lose
   1 B lose
   3 B win
   1 C lose
   2 C win


sedで - をスペースに置き換えてます。最初の1個だけ置き換えたいので、tr -d'-' とせず、gオプションも付けずにやって、1行にスペース区切りでチーム1,チーム2,スコア(m-n)と並べます。


$ cat result | sed 's/\-/ /'
A B 1-2
B A 3-1
C A 1-0
B C 5-4
C B 2-1


この後、勝ったチームの判別は、スコアが m-n って形式で表されてるので、引き算に見立ててそのままbcに渡して答えが0より大きいかどうかで見分けて、win/loseを出力してます。

awkならいい感じに$nに値が入りますが、bashだとそうも行かず、(いかないですよね?)

[ $(cut -d' ' -f 3 <<<${S}) -gt $(cut -d' ' -f 4 <<<${S}) ] 
より
[ $(cut -d' ' -f 3 <<<${S} | bc) -gt 0 ]
の方が短いので、この答えとしました。

winじゃなくてwonじゃないの?とか、英語的なツッコミはどうか許してください。


ヒアストリングス便利、というかだいぶ慣れてきました。
curlでWeb APIたたくのは実際にやってるの見て便利だわ、と納得。jqも便利そう。

テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ

トラックバック(0件)

タイトル (本文) ブログ名/日時

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
「第12回本当は怖くないシェル芸勉強会」に参加してきました th0x0472.log/BIGLOBEウェブリブログ
文字サイズ:       閉じる