たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

第38回シェル芸勉強会@大阪サテライトに参加しました

シェル芸勉強会に参加してきました

参加しました

ライブストリーミングYouTube上にも残っているので気になる方はご覧くださいな

www.youtube.com

午前の部

前回に続き、鳥海さんによる文字コードのお話でした。

twitter.com

まずはShift-JISについてで、歴史的経緯や区点番号についてなどが語られました。
特に興味深かったのはダメ文字についてで、

$ echo|nkf -s
[文字化け]\
$ echo|nkf -s
[文字化け]|

と言うようにnkfなどを使ってShift-JISに変換すると、2byte目に制御文字が出てきてしまう文字をダメ文字と言うらしいです。

\が出てしまうものをソ系|が出てしまうものをポ系のダメ文字と呼ばれていると言うのがとても面白かったです。

というわけでテキトウに難読化に使ってみました。

$ eval "$(__=$(nkf -s <(echo));echo echo ZGF0ZQo=${__:1}base64 -d${__:1}bash)"
2018113日 土曜日 21:24:14 JST

変数への代入と展開でパイプを隠蔽してみました。何かに応用できたら良いですね!

午後の部

今回は事前に数学系だと聞いていたのでヤバそうだなーと思いながら挑みました。問題と解答例はここです。

問1

echo 'jus共催 第38回҈҈҉҈҈҉シ҈҉ェ҈҉ル҈҉芸҈҉勉҈҉強҈҉会' からはじめて、文字列中のモヤモヤを取る問題。モヤモヤの正体はキリル文字の結合文字なのでxxdなどでバイナリ値を見て削るのが良さそう

$ echo 'jus共催 第38回҈҈҉҈҈҉シ҈҉ェ҈҉ル҈҉芸҈҉勉҈҉強҈҉会' | xxd -ps
7573e585b1e582ac20e7acac3338e59b9ed288d288d289d288d288d289
e382b7d288d289e382a7d288d289e383abd288d289e88ab8d288d289e58b
89d288d289e5bcb7d288d289e4bc9a0a

d288d289 というのがキリル文字っぽいのでsedで取り除く

$ echo 'jus共催 第38回҈҈҉҈҈҉シ҈҉ェ҈҉ル҈҉芸҈҉勉҈҉強҈҉会' | xxd -ps | sed 's/d28[8|9]/g|xxd -ps -r'
jus共催 第38回シェル芸勉強会

後はxxdでもとに戻せばOKですね。絵面はヤバイですが簡単な問題でした。

問2

任意の文字列に含まれる文字の内、提供されたファイル 仏説摩訶般若波羅蜜多心経 の中身にも含まれる文字を探す問題。例を挙げると

$ echo 不摂生|何らかのワンライナー
不
生

ファイルの中に不と生だけが含まれているので、こう出力するのが正しいというわけですね。それではやってみましょう

$ echo 不摂生|grep -o .|xargs -n1 -I@ echo "grep @ ./仏説摩訶般若波羅蜜多心経 &> /dev/null && echo @"|bash
不
生

最近 |xargs -n1 -I@ echo "ワンライナー" | bash というパターンにハマっているのでこの問題もコレでやってみました。不摂生という文字列をgrep -o .で1文字ずつに区切った後、それぞれgrepでファイルから検索しています。正常終了すれば含まれるので、echo しておきます。

問3

提供されたファイルedoの中身を年代順に並べてください

# cat ./edo
元禄
安政
元和
享保

元号を年代順に並べる問題ですね。本当の問題文にはヒントがあり、スクレイピングをすると良いらしいです。それではやってみます

$ w3m -dump "ja.wikipedia.org/wiki/元号一覧_(日本)" | grep -f <(cat ./edo)|tail -n4
                元和1615-1624
                元禄1688-1704
                享保1716-1736
                安政1855-1860

ちょっと余計なのがついてますが、w3mで取ってきて、grepするとキレイに並んでいるのが見つかりました。下から4行がコレだったのでtail -n4で取り出して答えです。

問4

エクセルの列番号XYZは何番目でしょうか。

エクセルなどの表計算ソフトでは列にアルファベットを使った26進数がよく使われるのですが、この並びの中でXYZが何番目かを求めます。コレはなぜか問題ページに答えが書いてあったので、コレしか思いつかねえなと思って流しました。

$ echo {A..Z} {A..Z}{A..Z} {A..Z}{A..Z}{A..Z} | tr ' ' \\n | grep -n XYZ
16900: XYZ

ブレース展開で列番号を作ってgrepするだけですね。

問5

罠にドはまりしてたので修正しました

標準偏差が10、平均が0の正規分布に従う乱数を発生させてヒストグラムを出してください

????????なんで????

$ csharp -e "
var rnd = new Random();
double X,Y;
double z1,z2;
for(var i=0;i<10000;i++) {
X=rnd.NextDouble();
Y=rnd.NextDouble();
z1=Math.Sqrt(-2.0*Math.Log(X)) * Math.Cos(2.0*Math.PI*Y);
z2=Math.Sqrt(-2.0*Math.Log(X)) * Math.Sin(2.0*Math.PI*Y);
Console.WriteLine((int)(z1*10+1000));
Console.WriteLine((int)(z2*10+1000));
}"|sort |uniq -c|sort -n -k2|awk '{for(i=0;i<$1/20;i++){printf "@"}print "\t"$1,$2-1000}'
@       1 -40
@       1 -37
@       3 -36
@       1 -34
@       2 -33
@       4 -32
@       7 -31
@       18 -30
@       13 -29
@@      22 -28
@       19 -27
@@      28 -26
@@      36 -25
@@@     48 -24
@@@@    75 -23
@@@@    77 -22
@@@@@   92 -21
@@@@@@  109 -20
@@@@@@@ 138 -19
@@@@@@@@@       169 -18
@@@@@@@@@@@     212 -17
@@@@@@@@@@@@@   241 -16
@@@@@@@@@@@@@@  268 -15
@@@@@@@@@@@@@@@@@       335 -14
@@@@@@@@@@@@@@@@@@@@    385 -13
@@@@@@@@@@@@@@@@@@@@@   414 -12
@@@@@@@@@@@@@@@@@@@@@@@ 454 -11
@@@@@@@@@@@@@@@@@@@@@@@@        467 -10
@@@@@@@@@@@@@@@@@@@@@@@@@@      515 -9
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  594 -8
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 617 -7
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   736 -6
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   734 -5
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  754 -4
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   729 -3
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  759 -2
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@        791 -1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@       804 0
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@       811 1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@        791 2
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      678 3
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  742 4
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  754 5
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@       648 6
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  590 7
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  587 8
@@@@@@@@@@@@@@@@@@@@@@@@@@@     537 9
@@@@@@@@@@@@@@@@@@@@@@@ 442 10
@@@@@@@@@@@@@@@@@@@@    397 11
@@@@@@@@@@@@@@@@@@@@    398 12
@@@@@@@@@@@@@@@@@       324 13
@@@@@@@@@@@@@@  279 14
@@@@@@@@@@@@    225 15
@@@@@@@@@@@     215 16
@@@@@@@@@@      184 17
@@@@@@@@        144 18
@@@@@@  115 19
@@@@@@  105 20
@@@@    73 21
@@@@    71 22
@@@     54 23
@@@     42 24
@@      30 25
@@      26 26
@       15 27
@       15 28
@       12 29
@       7 30
@       5 31
@       4 32
@       3 33
@       2 34
@       1 35
@       1 36
@       1 40

ヒストグラムは解答例を参考にしました。乱数生成はC#を使ってボックスミューラー法で行います。

問6

広済寺ホームページから妙法蓮華経の全文をダウンロードして、仏説摩訶般若波羅蜜多心経 と4文字連続で一致するところを探しなさい

なに?

$ cat ./myoho_shinji.txt|grep -of <( cat ./仏説摩訶般若波羅蜜多心経|sed 's/。/\n/g'|sed '/^$/d'|sed 's/..../&\n/g'|sed '/^$/d'|grep -o ....)|sort |uniq 
究竟涅槃
三世諸仏
即説呪曰
得阿耨多
般若波羅
亦復如是
羅三藐三

多分誤答です。コレは4文字ずつぶつ切りにして検索しただけなので。問題の意図は1文字ずつずらした4文字連続とのこと。これは時間内に解けませんでした。一番難しかった・・・

問7

a^2+b^2a*b+1で割り切れる正の数の組み合わせを生成してください。またチェックできたらしてください

$ echo {1..1000}_{1..1000} |tr ' ' '\n'| awk -F_ '$1<$2&&($1*$1+$2*$2)%($1*$2+1)==0{print $1,$2,($1*$1+$2*$2)/($1*$2+1),sqrt(($1*$1+$2*$2)/($1*$2+1))}'|column -t         

$ csharp -e "for(var a=1;a<1000;a++) for(var b=1;b<1000;b++) if((a*a+b*b)%(a*b+1)==0) Console.WriteLine($\"{a} {b}\");"|awk '{print $1,$2,($1*$1+$2*$2)/($1*$2+1), sqrt(($1*$1+$2*$2)/($1*$2+1))}'|column -t         

2    8     4    2
3    27    9    3
4    64    16   4
5    125   25   5
6    216   36   6
7    343   49   7
8    30    4    2
8    512   64   8
9    729   81   9
10   1000  100  10
27   240   9    3
30   112   4    2
112  418   4    2

チェックが甘いですが、これで解答としました。どちらもa,bを1から1000で動かして全探索しました。

問8

x[i+1]=a*x[i]*(1-x[i]) を無限に繰り返し、重複しないように1,000,000個数を出力する問題。x[0]=0.5、aは任意だが3<=a<4

awkではじめてと書いてあるのでawkでストリームを作って重複処理をすれば良さそうです

awk 'BEGIN{x=0.5;a=3.0;while(1){x=a*x*(1-x);print x}}'|awk '{x[$1]++;if(x[$1]==1)print $1}'|head -n1000000

先のawkで無限に数を生成し、後のawk連想配列を用いた重複の除外を行っています。しかしコレ、1,000,000個出そうと思っても桁が足りず一生終わらないので、awkOFMT="%0.20f"をつけなければならないです。

さらにこの問題実はカオスなので(カオス理論の方)、適切にaを与えれば重複処理が必要ないです。なので最終的には

$ awk 'BEGIN{OFMT="%0.20f";x=0.5;a=3.99;while(1){x=a*x*(1-x);print x}'|head -n1000000

です。

LT

今回もLTさせてもらいました。初っ端だったので緊張しましたが

www.slideshare.net

今回は~/.bashrcにイタズラされてしまったので、その対抗策として~/.bashrcを難読化する手法を提案しました。
欠点だらけなんですが、まあ大目に見てほしいです

終わり

今回もとても楽しかったです。東京会場のLTも盛り上がったみたいのでこれからアーカイブを見ようと思います。参加された皆様、企画側の皆様、ありがとうございました!