【参加記録】「第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
・・・

Q3.png

A3

$ cat red.txt | w3m -dump | less
・・・
perESC[KseESC[Kvering
furtivenESC[KesESC[Ks's
remeESC[KdiESC[Ked
・・・

A3.png


Q4

端末に次のように描画してください。

Q4.png

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    "

A4.png

ちなみに、以前作った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等で処理する場合、できる人はforwhile文を使わないでやってみましょう。

(添付の図は劣化しているかもしれませんのでリポジトリ内のファイルをお使いください。)

Q6.pgm

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

A6.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
Written on November 8, 2021