【問題と解答】jus共催 第43回大暴れシェル芸勉強会
Sat Aug 10 16:50:58 JST 2019 (modified: Sat Aug 10 16:50:58 JST 2019)
views: 2806, keywords:プログラミング,勉強会,シェル芸,シェル芸勉強会 この記事は最終更新日が5年以上前のものです。
- 問題で使われているデータファイルはGitHubにあります。クローンは以下のようにお願いします。
git clone https://github.com/ryuichiueda/ShellGeiData.git $
- 環境: 解答例はUbuntu Linux 18.04 で作成。Macの場合はcoreutilsをインストールすると、GNUのコマンドが使えます。BSD系の人は玄人なので各自対応のこと。
Q1
echo あいうえお
から始めて次のように出力してください。
あいいうううええええおおおおお
解答例
$ echo あいうえお | grep -o . |
awk '{for(i=1;i<NR;i++)printf $0;print}' |
tr -d \\n | awk 4
あいいうううええええおおおおお
Q2
たかし君は1個11円のうまい棒と1個21円のチロルチョコと1個54円のよっちゃんイカを223円分購入しました。それぞれいくつずつ購入したでしょうか?それぞれ最低一個は購入しているものとします。
解答例
何も考えずに計算機に任せるのが吉。
$ echo -e {1..22}\\t{1..12}\\t{1..10} | tr ' ' \\n | awk '$1*11 + $2*21 + $3*54 == 223'
2 7 1
Q3
次の10進数表現されたIPアドレスを2進数32桁に変換してください。できた人は逆変換の方法も考えてみてください。
192.168.10.55
解答例
dc
を使った例です。(dc
を使ってみたかったら出題しました。)
$ echo 192.168.10.55 | tr . \\n | while read n ; do echo $n |
dc -e '10i?2op' | xargs printf "%08d" ; done | awk 4
11000000101010000000101000110111
逆変換はこんなかんじで。
$ echo 11000000101010000000101000110111 | fold -b8 |
awk -F "" '{for(i=1;i<=NF;i++)a+=a+$i;print a;a=0}' | xargs | tr ' ' .
192.168.10.55
Q4
双子素数を出力していってください。双子素数とは、差が2となる素数のペアのことです。
3 5
5 7
11 13
・・・
解答例
$ seq inf | factor | awk 'NF==2&&$0=$2' | awk 'NR!=1{print a,$1}{a=$1}' | awk '$2-$1==2'
3 5
5 7
11 13
17 19
29 31
41 43
59 61
71 73
101 103
107 109
・・・
Q5
1から9の整数の組み合わせで、足して10になり、互いに数字が異なる組み合わせ(順番を入れ替えたものを含む)を全て列挙してください。
解答例
$ seq 4321 | grep -v 0 | grep -Ev '(.).*\1' |
awk -F '' '{for(i=1;i<=NF-1;i++)$5+=$i;if($5==10)print}' | sed 's/ 10$//'
Q6
次のnums
ファイルについて、Q5のような数字の並びになっている部分を、何行目に存在したかと共に出力してください。
$ cat nums
124123541
321412412
352381324
124214535
433251244
解答例
$ for i in {1..8} ;
do sed -r "s/.{"$i"}//" nums | grep -nof <(seq 4321 | grep -v 0 | grep -Ev '(.).*\1' |
awk -F '' '{for(i=1;i<=NF-1;i++)$5+=$i;if($5==10)print}' | sed 's/ 10$//' | tr -d ' ') ;
done | sort -u
1:235
1:4123
1:541
3:1324
3:523
4:145
5:325
Q7
次のような100x100ピクセルのビットマップファイルを作ってください。
解答例
$ echo P1 100 100 $(seq 10000 | awk '{print ($1+int(($1-1)/100))%2}') |
convert - check.bmp
Q8
check.bmp
を何か文字列をワンライナーで仕込んだビットマップに変換し、ビットマップからその文字を抽出して端末に表示してみてください。文字列を仕込んだビットマップは画像として開けることを確認のこと。
解答例
$ a=$(xxd -ps <<< うんこ); b=$(sed s/././g <<< $a) ; xxd -ps check.bmp | sed '$s/'$b'$/'$a'/' | tr -d \\n | xxd -p -r > bad.bmp
$ cat bad.bmp | tail -c 10
うんこ
Q9
さらに、文字列を仕込んだビットマップをpng形式にして、さらにそれをビットマップに復元して仕込んだ文字が読めることを確認してください。
解答例
- png形式へ(無圧縮にしなければならない)
$ convert -depth 24 -define png:compression-level=0 bad.bmp bad.png
- bmpへの復元
いろいろ試しましたがppm経由で変換すると余計なオプションが不要な模様です。
$ convert bad.png ppm:- | convert - toobad.bmp
$ cat toobad.bmp | tail -c 10
うんこ