日々之迷歩

世の中わからんことだらけ

ITが複雑で難しくなっていく様に翻弄される日々です。微力ながら共著させていただいた「シェル・ワンライナー160本ノック」をよろしくお願い申し上げまする。

「第44回シェル芸勉強会:福岡サテライト」レポート

実に1年ぶり!シェル芸勉強会の福岡サテライトを開催出来た、ようやく。今回の会場は、福岡市エンジニアカフェのメインホールを使わせていただいた。参加者は全部で5人で、初参加者は3人。

勉強会募集サイト

本家東京会場募集

usptomo.doorkeeper.jp

大阪サテライト会場募集

https://atnd.org/events/109053atnd.org

福岡サテライト会場募集

https://atnd.org/events/109099atnd.org

長崎サテライト会場募集

shell-nagasaki.connpass.com

イベント報告関連

見つけたら追記予定

会場

今回は福岡市の天神・赤煉瓦文化館内にある「エンジニアカフェ」のメインホールを始めて利用した。 イベントの会場として利用するには、初回はコミュニティマネージャの方と対面で面談が必要。 各施設・設備は無料で利用可能。メインホールではプロジェクターやインターネット接続が利用出来る。プロジェクターはRGBやHDMI接続以外に、AppleTV経由でのAirPlayが使えるのが便利だった。

engineercafe.jp

twitter.com

twitter.com

twitter.com

スライド資料

どちらも話す時間が無かったのだが、ここに晒しておく。

speakerdeck.com

speakerdeck.com

午前の部

午前中はぷるさんによるJavaScript入門。動画と資料はこちら。

www.youtube.com

twitter.com

JavaScripのObjectコピーは参照渡しなのよ。値渡しにするには{...Obj}みたいな書き方するらしいのよ。nodeはNode.jsのREPL環境。

$ node
> obj1 = {key:1}
{ key: 1 }
> obj2 = obj1
{ key: 1 }
> obj3 = {...obj1}
{ key: 1 }
> obj1.key = 2
2
> obj1
{ key: 2 }
> obj2
{ key: 2 }
> obj3
{ key: 1 }
> 

まあでもRubyのハッシュも参照渡しだったわね。pryはRubyのREPL環境。

$ pry
[1] pry(main)> hash1 = {:key=>1}
=> {:key=>1}
[2] pry(main)> hash2 = hash1
=> {:key=>1}
[3] pry(main)> hash1[:key] = 2
=> 2
[4] pry(main)> hash1
=> {:key=>2}
[5] pry(main)> hash2
=> {:key=>2}
[6] pry(main)> 

午後の部

第44回シェル芸勉強会(午後の部) www.youtube.com

「無」を「保証」するという名言出たぞ。今回の問題が出来る人はどこ行っても通用するらしいぞ。問題と解答はこちら。コマンドの組み合わせで華麗に解くとかじゃ無く、awkでゴリゴリ頑張る系らしいぞ。

【問題と解答】jus共催 第44回シェル芸7周年で変態化が進みすぎなので実用的な問題しか出さないぞと宣言しておく勉強会(無保証) | 上田隆一の仕事とか

自分なりの解答例がこちら。今回は非常に頭を使う問題だった。最初は「数独」を理解していなかったので、問題の意図が分からず置いてけぼりになりかけた。

Q1

第3フィールド以外はとりあえず無視して、行、列、値だけなら簡単。FS=は列(フィールド)の区切り文字を空文字に指定、要するに1文字ずつ区切るということ。オプションで-F ''と指定しても同様。

$ cat sudoku | awk '{for(i=1;i<=NF;i++){print NR-1,i-1,$i}}' FS=
0 0 5
0 1 3
0 2 *
0 3 *

次に第3フィールドを考えるのだが、この後がわからなかったので会長の解答例を。3つずつ同じ物が続くということは、3で割って切り捨てれば良いということだった。

$ cat sudoku | awk '{for(i=1;i<=NF;i++)print NR-1,i-1,$i}' FS= | awk '{print $1,$2,int($1/3)%3*3+int($2/3),$3}'
0 0 0 5
0 1 0 3
0 2 0 *
0 3 1 *

Q2

ギブアップ!動画見て確認しよう・・

Q3

チョット頭悪い解答を晒しておく。

$ cat b | cut -c9- | tr -d ' ' | while read s; do [ -n "$s" ] && echo 123456789 | tr -d $s || echo; done | sed 's/./& /g' | paste -d ' ' a - | sed 's/ *$//'

ポイントはこちら。例えば「1、3、5、6」以外の数字は何になるかはこうしてる。

$ echo 123456789 | tr -d 1356
24789

Q4

前半はデータを行列のマトリックスに戻す問題。ただし下記のような行は値が確定している(入る数字の候補が1つに絞られている)

...
4 4 4 * 5
...
6 5 7 * 7

値が確定している行は列数が5個になっているのを利用した解答がこちら。パターンがNF==5NF!=5の2種類出現する。

$ cat c | awk 'NF==5{a[$1+1,$2+1]=$5}NF!=5{a[$1+1,$2+1]=$4}END{for(i=1;i<=9;i++){for(j=1;j<=9;j++){printf a[i,j]}print ""}}'
53**7****
6**195***
*98****6*
8***6***3
4**853**1
7***2***6
*6***7284
***419*35
****8**79

ナンバープレースの問題は解けず。

Q5

積分は要するに細かい長方形の足し算という雑な解答がこちら。もっと精度を上げるには、会長の解答のように台形の足し算にしよう。

$ seq 0 0.001 0.5 | awk '{printf "%.20f\n",log((cos($1)))*0.001}' | numsum
-0.0214458744608356

seqコマンドは引数を3つ指定すると、第二引数が増分になる。

$ seq 0 0.001 0.5
0.000
0.001
0.002
...
0.498
0.499
0.500

numsumコマンドは、数値のリストを足し算する。

$ seq 1 3 | numsum
6

Q6

色々とスマートな解答が出ていた。自分なりの解答がこちら。

まずspeechファイルで空行の行番号を取り出し、speech2ファイルの行頭に順次付加する。

$ cat speech | awk 'length==0{printf "%02d\n",NR}' | paste -d' ' - speech2
03 んこも休み休み言え
04 春はあけぼの。夏は
07 ビも無ェ、うんこも
09 かた見だごとア無ェ
12 した。あなたのうん
13 こですお前それうん
14 こでも同じ事言えん

speechファイルには、行頭に行番号を付加する。

$ awk '{printf "%02d %s\n",NR,$0}' speech
01 このうんこを作った
02 のは誰だあっ!!う
03 
04 
05 夜。秋は夕暮れ。冬
06 はうんこハァ テレ
07 
08 無ェ、生まれてこの
09 
10 やつはとんでもない
11 ものを盗んでいきま
12 
13 
14 
15 の?疲れからか、

後はこの2つのデータをOUTER JOINすれば良い。行番号はゼロ埋めした固定長にしている。これはjoinコマンドを使って結合する際にキーが辞書順に並んでいる必要があるためだ。

$ cat speech | awk 'length==0{printf "%02d\n",NR}' | paste -d' ' - speech2 | join -a 2 - <(awk '{printf "%02d %s\n",NR,$0}' speech)
01 このうんこを作った
02 のは誰だあっ!!う
03 んこも休み休み言え 
04 春はあけぼの。夏は 
05 夜。秋は夕暮れ。冬
06 はうんこハァ テレ
07 ビも無ェ、うんこも 
08 無ェ、生まれてこの
09 かた見だごとア無ェ 
10 やつはとんでもない
11 ものを盗んでいきま
12 した。あなたのうん 
13 こですお前それうん 
14 こでも同じ事言えん 
15 の?疲れからか、

Q7

RSA暗号に関する問題だった。

小問1

巨大な整数の乗算と剰余計算出来るか?が壁。bcコマンドの力を利用した解答がこちら。 まず計算する式の文字列を作成する。

$ cat message | tr ' ' '\n' | sed 's/$/^200%437/'
262^200%437
325^200%437
122^200%437
80^200%437
266^200%437
406^200%437
163^200%437
89^200%437
325^200%437
89^200%437
326^200%437

後はbcコマンドに食わせて、xargsで横に並べて完成。

$ cat message | tr ' ' '\n' | sed 's/$/^200%437/' | bc | xargs
35 308 26 282 399 87 349 55 308 55 85

awkで計算するにはコツが必要で、GNUのMPFR、MPライブラリを利用する。

#数が大きすぎて桁が溢れてしまう
$ awk 'BEGIN{print 262^200%437}'
-nan

# -MオプションでGNUのMPFR、MPライブラリを有効にする。
$ awk -M 'BEGIN{print 262^200%437}'
35

GNUのMPFR、MPライブラリを利用するには、コンパイル時に組み込まれている必要がある。 --versionオプションで確認出来る。

$ awk --version
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)
...

小問2

ギブアップ!

小問3

ギブアップ!

終わりに

久しぶりに福岡サテライトを開催したが、頭を使う問題が多くて初参加者へのフォローがしっかり出来たか自信が無い。まあでも自分なりにやる事はやったと思う。 毎回これでもかという高難易度で参加者の方は大変だと思うが、これに喰らい付けている人はかなり貴重なのでは?とも思ったのであった。それ以上に問題を作成する上田さんが最高級にお疲れ様なのである。