【問題と解答】jus共催 第43回大暴れシェル芸勉強会

Sat Aug 10 16:50:58 JST 2019 (modified: Sat Aug 10 16:50:58 JST 2019)
views: 2314, keywords:プログラミング,勉強会,シェル芸,シェル芸勉強会 この記事は最終更新日が4年以上前のものです。

  • 問題で使われているデータファイルは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
   うんこ
ノート   このエントリーをはてなブックマークに追加 
 

prev:【問題のみ】jus共催 第43回大暴れシェル芸勉強会 next:jus共催 第43回シェル芸勉強会リンク集

やり散らかし一覧

記事いろいろ