【参加記録】「第56回シェル芸勉強会」の解答例
概要
- イベント名: jus共催 第56回シェル・ワンライナー160本ノックアウトシェル芸勉強会
- 開催日: 2021年10月30日(土)
問題 | 結果 | 個人的難度 | コメント |
---|---|---|---|
Q1 | ✓ | ★☆☆☆☆ | 1問目なので楽 |
Q2 | ✓ | ★☆☆☆☆ | Tukubaiのtateyoko が便利 |
Q3 | ✓ | ★☆☆☆☆ | w3m -dump でチート |
Q4 | ✓ | ★★☆☆☆ | テトリス風画像を力技で描く |
Q5小問1 | ✓ | ★★☆☆☆ | このあたりから難しくなる |
Q5小問2 | ✘ | ★★★☆☆ | 小問1の出力を差し込むのに手間取る |
Q6 | ✘ | ★★★★☆ | ImageMagick単体では解けなかった |
Q7 | ✘ | ★★★★★ | 真っ当なスペックのPCがほしい |
- 問題および出題者による解答例:
- 参考リンク:
Q1
日本語を入力せずに、端末に
月月火水木金金
と出力してください。
A1
$ echo e69c88e69c88e781abe6b0b4e69ca8e98791e987910a | xxd -p -r
月月火水木金金
# LANG=ja_JP.utf8と設定してから実行
$ cal | awk 'NR==2{$1=$2;$7=$6;print}' | tr -d ' '
月月火水木金金
Q2
次のコマンドからパイプをつなげて、「今日の仕事は、楽しみですか。」と出力してください。
echo 今楽日しのみ仕で事すはか、。
A2
# Open usp Tukubaiのコマンドtateyokoを使用
$ echo 今楽日しのみ仕で事すはか、。 | grep -o . | xargs -n2 | tateyoko | tr -d ' \n'; echo
今日の仕事は、楽しみですか。
なお、Open usp Tukubaiは「https://github.com/usp-engineers-community/Open-usp-Tukubai」から入手できます。
Q3
red.txt
から色(ANSIカラーコード)を除去してください。特に一般解を考える必要はありません。
$ less red.txt
・・・
perESC[01;31mESC[KseESC[mESC[Kvering
furtivenESC[01;31mESC[KesESC[mESC[Ks's
remeESC[01;31mESC[KdiESC[mESC[Ked
・・・
A3
$ cat red.txt | w3m -dump | less
・・・
perESC[KseESC[Kvering
furtivenESC[KesESC[Ks's
remeESC[KdiESC[Ked
・・・
Q4
端末に次のように描画してください。
A4
# 結果は次の図の通り
$ echo -e "\e[41m \e[0m\n \e[41m \e[0m \e[44m \e[0m\n \e[44m \e[43m \n\e[46m \e[0m \e[44m \e[43m "
ちなみに、以前作ったCLIでGUIなテトリス風ゲームが「https://github.com/mikkun/AWKTC」に置いてあります(少し宣伝)。
Q5
ros_log
ファイルは、複数のプロセスがログを書き込んだファイルです。次のようにVALUE
という文字列をgrep
で検索すると、行の最初の文字列が欠けている行があります。
$ grep VALUE ros_log
・・・
[ INFO] [1634194849.754396571, 267.092000000]: VALUE ITERATION END
31, 306.723000000]: VALUE ITERATION START
[ INFO] [1634194901.293168836, 318.602000000]: VALUE ITERATION END
・・・
小問1
この、欠けている文字列をros_log
から探してください。
小問2
欠けている部分を上のgrep VALUE ros_log
の出力につなげて、各行に描いてあるふたつの数字の差を出力してください。左の数字はシステムの時刻、右の数字はプログラムが走り出してからの秒数なので、すべての行の差が(だいたい)一致すると、正しく復元していることが分かります。
A5
小問1
# 各行の2つの数字のフォーマットは「10桁.9桁, 2または3桁.9桁」になっているので「10桁.7桁」で途切れている行を探す
$ grep -P '\D\[\d{10}\.\d{7}\D' ros_log | sed -E 's/.*(\[ INFO\] \[[0-9]{10}\.[0-9]{7}).*/\1/'
[ INFO] [1634194889.4049047
小問2
$ grep VALUE ros_log | sed -E '/^[0-9]/s/^/'"$(grep -P '\D\[\d{10}\.\d{7}\D' ros_log | sed -E 's/.*(\[ INFO\] \[[0-9]{10}\.[0-9]{7}).*/\1/')"'/' | sed -E 's/.*\] \[//;s/\].*//;s/\,/-/' | bc -l
1634194582.516889867
1634194582.524089069
1634194582.546207875
1634194582.554429903
1634194582.562755427
1634194582.571231380
1634194582.584208496
1634194582.591130748
1634194582.617389194
1634194582.625124281
1634194582.653935414
1634194582.662396571
1634194582.681904731
1634194582.691168836
1634194582.705154334
1634194582.712970195
Q6
house.pgm
は、ある環境の地図です。この地図は1画素で5cm四方の領域に物があるかないかを示したものですが、1画素10cm四方に解像度をさげたいと考えました。田字型の4区画で、値が最も小さい(色の濃い)画素を残す方法で、解像度を下げてhouse_s.pgm
というファイルに保存してください。
基本的に画素をAWK等で加工する解を想定していますが、できる人はImageMagickを使ってもかまいません。また、AWK等で処理する場合、できる人はfor
やwhile
文を使わないでやってみましょう。
(添付の図は劣化しているかもしれませんのでリポジトリ内のファイルをお使いください。)
A6
# できない人なので、x軸とy軸に対してそれぞれawkコマンドでfor文を使い2画素ごとに小さい値のほうを残す
# 結果は次の図の通り
$ convert house.pgm -compress None pgm:- | awk 'NR>5{for(i=1;i<=NF/2;i++){j=2*i;printf "%d ",$(j-1)<$j?$(j-1):$j}printf "\n"}' | tateyoko | awk '{for(i=1;i<=NF/2;i++){j=2*i;printf "%d ",$(j-1)<$j?$(j-1):$j}printf "\n"}' | tateyoko | awk 'BEGIN{printf "P2\n192 192\n255\n"}1' > house_s.pgm
Q7
a^3 + b^3 = 6963472309248、a <= bとなる整数の組(a,b)を全て求めてください。できる人は、48988659276962496に対して同様に(a,b)を求めてください(桁落ち注意)。
A7
# 出力が得られるまでとても時間がかかるので注意(我がオンボロPCで約15分以上)
# 桁落ち対策として1回めのawkコマンドでは-MオプションをつけてMPFR拡張を有効化
# なお、48988659276962496に対しては、当PCでは桁落ち以前の問題ということで解答は棚上げ :-(
$ L=$(node -e 'console.log(Math.ceil(Math.cbrt(6963472309248)))'); seq $L | awk -M -v L=$L 'BEGIN{N=6963472309248}{a=$1;n1=N-a^3;for(b=1;b<=L;b++){if(a>b)continue;n2=n1-b^3;printf "%d %d %d\n",a,b,n2}}' | awk '$3==0{print $1,$2}'
2421 19083
5436 18948
10200 18072
13322 16630