〜2016年5月上旬〜
というわけで2問目。
パイプより右側はマルチバイト文字を使わないという条件があるので注意。
どこをいじるかは決め打ちでいいので難しくはない。
等幅フォント前提と考えれば「醤油ラ」の3文字の2倍で6個の空白分だけインデントさせればいい。
% echo カレーライス 醤油ラーメン | (read a b; grep -o . <<<$a | sed "s/^/ /;3c$b") カ レ 醤油ラーメン ラ イ ス
キモはread a bで一旦変数に入れてしまうと扱いやすい。
% echo カレーライス 醤油ラーメン | (read a b; grep -o . <<<$a | sed "3\!s/^/ /;3s/./$b/")
とかやると3\!sの扱いがbashで面倒なことになるのでやめた。
そのおかげで3cを思い付いたのでよしとしよう。
3問目。
Q3.ansにはなぜ空白が2つあってソートされてないのかという点を考慮するとこうなる。
% cat Q3 | awk '{a[$0]=a[$0]" "NR}END{for(i in a)print i, a[i]}' bababa 2 5 aaabbb 1 3 4 bbbbba 6
まったくもって模範解答と同じである。復元もやってることは同じ。
% cat Q3.ans | awk '{for(i=2;i<=NF;i++)a[$i]=$1}END{for(i=1;i<=length(a);i++)print a[i]}' aaabbb bababa aaabbb aaabbb bababa bbbbba
ソートする代わりに配列を使っているだけ。
4問目。
素数といえばfactorなので。
% factor {1..8} | paste - Q4 | awk 'NF==3{a[$NF]++}END{for(i in a)print i, a[i]}' みかん 1 りんご 3
後半は全部awkで解いてるが基本的にはこれも模範解答と同じ。
例のprimesを使うならこんな感じ。
% primes 2 8 | sed 's/$/p/' | sed -nf- Q4 | sort | uniq -c 1 みかん 3 りんご
sedでsedスクリプトを生成し、
% primes 2 8 | sed 's/$/p/' 2p 3p 5p 7p
Q4から抜き出す。
% primes 2 8 | sed 's/$/p/' | sed -nf- Q4 りんご みかん りんご りんご
あとは模範解答通り。
5問目。会長が15分じゃ解けないと言ってました。
素直に書くと3重ループになるのでかなり面倒。
面倒なのでRubyで解いてみたが、表示がだめだめすぎる。
% cat Q5 | ruby -ane '2.upto($F.size){|i|p $F.each_cons(i).map{|a|a.map(&:to_i)}.select{|x|x.inject(:+)==10}}' [[9, 1]] [[4, 4, 2], [2, 3, 5]] [] [] [] [] [] [] [] [] []
とりあえずちょっと見た目を整えておこう。
% cat Q5 | ruby -ane '2.upto($F.size){|i|$F.each_cons(i).map{|a|a.map(&:to_i)}.select{|x|x.reduce(:+)==10}.map{|x|p x}}' [9, 1] [4, 4, 2] [2, 3, 5] % cat Q5 | ruby -ane '2.upto($F.size){|i|$F.each_cons(i).select{|x|x.reduce(0){|r,e|r+e.to_i}==10}.map{|x|puts x*" "}}' 9 1 4 4 2 2 3 5
awkで考えてみたが、やはり模範解答とあまり変わらない。
% cat Q5 | awk '{for(i=1;i<=NF;i++){for(j=1;j<=NF-i;j++){a=s=$i;for(k=i+1;k<=j+i;k++){a=a" "$k;s+=$k};if(s==10)print a}}}' 4 4 2 2 3 5 9 1
6問目。
これもsedスクリプトを生成させるわけだが、awkでやってみた。
% sed "$(awk '{print "s/"$1"/"$2"/g"}' Q6_2)" Q6_1 所謂いわゆる「死相」というものにだって、 もっと何か表情なり印象なりがあるものだろうに、 人間のからだに駄馬の首でもくっつけたなら、 こんな感じのものになるであろうか、 とにかく、どこという事なく、見る者をして、 ぞっとさせ、いやな気持にさせるのだ。 私はこれまで、こんな不思議な男の顔を見た事が、 やはり、いちども無かった。
もちろん-f-でもいい。
% awk '{print "s/"$1"/"$2"/g"}' Q6_2 | sed -f- Q6_1 % sed 's| |/|;s|.*|s/&/g|' Q6_2 | sed -f- Q6_1
今日は7問目と8問目の2問。
特にひねりもないので。
% kill -9 $$
SIGTERMでは死ないのでSIGKILLで。
関数を定義してるところから宣言を生成し、所定の場所に挿入する。
% cat Q8.cc | sed '/void/!d;s/$/;/' | sed '/name/r/dev/stdin' Q8.cc | tee >(g++ -xc++ -) #include <iostream> #include <string> using namespace std; void aho(void); string nazo(void); void aho(void) { cout << nazo() << endl; } string nazo(void) { return "謎"; } int main(int argc, char const* argv[]) { aho(); return 0; } % ./a.out 謎
voidとかnameとかたまたまこの問題で使えるだけで本当ならちゃんとした正規表現でやるべき。
これもsedスクリプトを生成する方法が使える。
% cat Q8.cc | awk '/void/{print "/name/a" $0 ";"}' | sed -f- Q8.cc % cat Q8.cc | sed '/void/!d;s|.*|/name/a&;|' | sed -f- Q8.cc
真ん中のawkとsedのやってることは同じ。
次にawkで挿入。
awkだけで標準入力を読み込ませるには-で可能。
getlineで最初に全部読み込んでしまえばいいわけだ。
% cat Q8.cc | sed '/void/!d;s/$/;/' | awk 'BEGIN{while(getline < "-")p=p"\n"$0};1;/using/{print p}' Q8.cc
ちょっとまどろっこしいと感じるならこんな手も。
awkではファイル名を指定するところでQ8=1のように変数を初期化できる。
このQ8という変数は指定した順番通り-(標準入力)が読み終わった後で評価される。
つまりフラグとして使える。
% cat Q8.cc | sed '/void/!d;s/$/;/' | awk '!Q8{p=p"\n"$0;next};1;/name/{print p}' - Q8=1 Q8.cc
!Q8はFILENAME=="-"でいいわけだが、こんな方法もあるということで。
シェル芸勉強のLTでtrueの終了ステータスが137になった話。
なぜ137かというとこれはシェルがやってる。
Bourne shell系は137になるが、これは128+9を意味する。
9はSIGKILLだ。つまりkillされると128+そのsignalの番号となる。
% (sleep 5; echo $?) & killall -9 sleep [1] 20526 137 % (sleep 5; echo $?) & killall -2 sleep [1] 21126 130
内部コマンドのkillは-lで名前を教えてくれる。
% bash -c 'kill -l 2 9 130 137' INT KILL INT KILL % zsh -c 'kill -l 2 9 130 137' INT KILL INT KILL
だからこうするとわかりやすい。
% (sleep 5; kill -l $?) & killall -1 sleep [1] 23383 HUP
128+SIGじゃないシェルも存在するらしい。
xargsだとquote文字のエスケープが面倒なことになるので、
そういうときはGNU Parallelがお勧め。
% seq -w 0 99999999999 | parallel --pipe -q mawk '{c=($1*6+$2*5+$3*4+$4*3+$5*2+$6*7+$7*6+$8*5+$9*4+$10*3+$11*2)%11;d=c<=1?0:(11-c);print $0 d}' FS=
--pipeで各々標準入力に入れてくれるし、適当に入力も分割してくれる。
さらにデフォルトで現在のコア数をチェックしてその数で並列処理されるし、
-qをつけると面倒なquote処理までやってくれる。至れり尽くせりだ。
楽天のEdyViewerはブラウザで動くわけだけど、
EdgeではだめなようでWindows10でもIEを使う必要がある。
Windows10にそんなもんあるのかというと、
ちゃんとWindowsアクセサリに存在する。
でIE11でアクセスすればあっさり使えてしまうのであった。
縦書きPDFでも公開してるWeb小説があるんだけど、
なぜか1つのPDFになってるもんだから10000ページを超えている。
Sony Readerに入れてみて3000ページぐらいまでジャンプしてからページ送りしてみたら、
遅くて使い物にならない。というわけで適当に分割する。
とりあえず400ページで分割する。
pdftkだと
% pdftk foo.pdf cat 1-400 output foo-1.pdf % pdftk foo.pdf cat 401-800 output foo-2.pdf
という感じで実行できればいいので
% for i in {0..10000..400};do pdftk foo.pdf cat $[i+1]-$[i+400] output foo-$(printf %03d $[i/400+1]).pdf
としてみた。章とか無視してしまうがまあ気にしない。