Just another Ruby porter,

〜2016年2月中旬〜


<Older(,) | Newer(.)> | Recent(/)>> | RDF

2016-02-11 (Thu)

Project Euler Problem 28 #シェル芸

Number spiral diagonals. 螺旋状に並んだ数の対角線。
ながめているだけでいくらでも法則は見つかる。
一番簡単なのは小さいほうから順番に差分を取る。
2,2,2,2,4,4,4,4,6,6,6,6,8,8,8,8,...
となっている。これをそのままRubyで実装するとこうなる。

% ruby -e 'a=1;d=2;s=1;500.times{4.times{s+=a+=d};d+=2};p s'
669171001

awkに移植するとここんな感じ。

% seq 500|awk '{d+=2;for(i=0;i<4;i++){print a+=d}}' a=1|jq -s add+1
669171001

どうしても1が邪魔になるので最後にjqで足している。
for文を展開するとこうなる。

% seq 500|awk '{d+=2;print 4*a+10*d;a+=4*d}' a=1|jq -s add+1
669171001

さらにゴルフしてみたが、あまりきれいではない。

% seq 500|awk '$0=3*a+(a+=4*(d+=2))+6*d' a=1|jq -s add+1 
669171001

seqの結果を使ってないので高須クリニックでもいい。

% yes 高須クリニック|head -n 500|awk '$0=3*a+(a+=4*(d+=2))+6*d' a=1|jq -s add+1 
669171001

ちゃんとseqの結果を使うなら、右上の奇数の自乗数を使うのがいいかな。

% seq 3 2 1001|awk '$0=$0^2*4-6*(d+=2)'|jq -s add+1
669171001

4倍しちゃうと多すぎなので、調整している。

これは単純な数学の問題なのでたぶんそのものずばりな方程式もあるんだろうけど、
そっちのほうが長くなりそうな。


2016-02-12 (Fri)

Project Euler Problem 29 #シェル芸

Distinct powers. 個別のべき乗。
ひねりなし。

bc版。

% echo {2..100}\^{2..100}\; | BC_LINE_LENGTH= bc | sort -u | wc -l
9183

Ruby版。

% ruby -e 'p [*2..100].product([*2..100]).map{|a,b|a**b}.uniq.size' 
9183

2016-02-13 (Sat)

第21回シェル芸勉強会にYoutubeで参加 #シェル芸

今回はYoutubeでの配信からの参戦。
最初はPS3のYoutubeアプリで見てたけど、
PSNが不調でログインできなくなり、
AndroidのYoutubeアプリで視聴した。

_ Q1 bba.pdfからテキストを抽出:

pdftotextとかps2txtのようなコマンドが世の中には存在する。
うまくいかないこともあるが。

% pdftotext bba.pdf -

_ Q2 CP932のデータをUTF-8に変換し折り返して表示:

折り返してから変換すると考えるとfoldが使える。

% fold -35 anydata.cp932 | iconv -f cp932

_ Q3 2016年の日曜日:

date -fを使う。実はxargsを使うほうが難しい。

% seq -f '2015-12-31 %g day' 365|date -f- +'%w %F'|grep '^0'

Project Euler Problem 19で同じようなことをやったばかりだ。

_ Q4 データのjoin:

新データ優先。

% awk '!a[$1]++' newdata data | sort

結局のところuniqなのでsortでもok。

% sort -u -k1,1 newdata data

_ Q5 不正な文字:

適当にsedで変換したけど、これはどうなんだ。

% LANG=C sed -i 's/[\x80-\xff]\+//' a.bash; sed -i 's/˜/~/' b.bash

_ Q6 拡張正規表現を標準正規表現に変換:

題意を見失っていたが、perlで書いてみた。繰り返し文字があるとsedではきびしい。

% perl -pe 's/(?:\((.+?)\)|(.))\{(\d+)\}/($1||$2)x$3/eg;s/(\[.+\]|.)\+/$1$1*/g' extended 

_ Q7 各段落の文字数:

空白とか改行とか数えない。

% awk 'gsub(/\n/,"")&&$0=length' RS=' ' text

_ Q8 添付ファイルを抽出:

uudeviewなんて10年以上忘れてたよ。

Q8 % uudeview -i 1350369599.Vfc03I4682c8M940114.remote

awkでむりやりbase64 -dにつっこんでみた。

% awk -F\" '/filename=/{f=$(NF-1)}f&&!NF{c="base64 -d>"f;f=""}c,/^--/{print|c}' 1350369599.Vfc03I4682c8M940114.remote

余計なものが終わりにつくので「base64: 無効な入力」と言われちゃうが気にしない。


2016-02-14 (Sun)

Project Euler Problem 31 #シェル芸

Coin sums. 部分和問題。
Wikipediaにも載っているし、解法もわかっている。

初期値として0pを考えるとわかりやすいらしい。まずこれを1通りとする。
1pだけを使って1pから5pまで作る方法を考える。
1pを作るには1pを引いて0p、0pは1通りなので1pも1通り。
2pを作るには1pを引いて1p、1pは1通りなので2pも1通り。
3pを作るには1pを引いて2p、2pは1通りなので3pも1通り。
4pを作るには1pを引いて3p、3pは1通りなので4pも1通り。
5pを作るには1pを引いて4p、4pは1通りなので5pも1通り。
のように全部1通りになる。
次に1p,2pだけを使う場合。2p未満はやる必要はないので2pから5pで考える。
2pを作るには2pを引いて0p、0pは1通りなので2pも1通り。足して2通り。
3pを作るには2pを引いて1p、1pは1通りなので3pも1通り。足して2通り。
4pを作るには2pを引いて2p、2pは2通りなので4pは2通り。足して3通り。
5pを作るには2pを引いて3p、3pは3通りなので5pは2通り。足して3通り。
次に1p,2p,5pだけを使う場合。5p未満はやる必要はないので5pだけで考える。
5pを作るには5pを引いて0p、0pは1通りなので5pは1通り。足して4通り。
つまり1p,2p,5pを使って5pを作るには4通り存在する。
実際に 1+1+1+1+1, 2+1+1+1, 2+2+1, 5の4通りだ。
これをシェル芸で表現するとこうなる。

% echo 1 2 5 10 20 50 100 200|xargs -n1|awk 'BEGIN{a[0]=1}{for(i=$0;i<=200;i++)a[i]+=a[i-$0]}END{print a[200]}' 
73682

aという配列に200までの組み合わせ数が入る。
キャッシュしているようなものなので非常に高速だ。


2016-02-15 (Mon)

Project Euler Problem 30 #シェル芸

30番を飛ばしてた。
Digit fifth powers. 各桁の5乗。
まずは上限を探る。各桁の5乗の総和が何桁になると追い付けなくなるか計算。

% awk 'BEGIN{for(i=1;i<10;i++){s+=9**5;if(s<10^i)break};print i}'
6

上限は6桁とわかった。あとはawkで。6個ぐらいならループより並べちゃったほうが手っ取り早い。

% seq 10 $[6*9**5] | awk '$0==$1^5+$2^5+$3^5+$4^5+$5^5+$6^5' FS=
4150
4151
54748
92727
93084
194979

6個見つかった。足せば答えになる。

% seq 10 $[9**5*6] | awk '$0==$1^5+$2^5+$3^5+$4^5+$5^5+$6^5' FS= | jq -s add 
443839

2016-02-16 (Tue)

Kimono Labsが今月で閉鎖

Yahoo! Pipesから移行して半年ほど経ってようやく安定してきたかと思ったら。
まいったねえ。botはWerckerで動かすか。
1時間ごとのtwitterのbotならIFTTTのDate&TimeからMakerを起動し、
Werckerのwebhookを叩けばいけるはずだ。
webhookがあるならCircleCIでも何でもいいが。


2016-02-17 (Wed)

Project Euler Problem 32 #シェル芸

Pandigital products. パンデジタル積。
9個ということでいろいろ考えてみると、
1桁*4桁=4桁か2桁*3桁=4桁のどちらかしか可能性はない。
というわけで

% echo {2..9}\ {1234..9876}$'\n' {12..98}\ {123..987}$'\n'

が候補となる。あとはawkで実際に計算するわけだけど、明らかにだめなものを除外する。
5桁になるものと0を含むものがあったらチェックする必要はない。

| awk '(a=$1*$2)<1e4&&a$0!~/0/{print $1"*"$2"="a}'

2*1234=2468というような文字列を作っている。
*とか=とか不要だけど、わかりやすいように入れている。
あとはgrepで同じ文字が2個以上ないかチェックする。
後方参照でマッチすれば同じ文字があるということなので-vで除外。

| grep -v '\(.\).*\1'

積を抜き出して重複を除外し総和を求める。

| cut -f2 -d= | sort -u | jq -s add 

途中経過。

% echo {2..9}\ {1234..9876}$'\n' {12..98}\ {123..987}$'\n' \
| awk '(a=$1*$2)<1e4&&a$0!~/0/{print $1"*"$2"="a}' \
| grep -v '\(.\).*\1'
4*1738=6952
4*1963=7852
12*483=5796
18*297=5346
27*198=5346
28*157=4396
39*186=7254
42*138=5796
48*159=7632

5796と5346が重複している。


2016-02-18 (Thu)

Project Euler Problem 33 #シェル芸

Digit cancelling fractions. 桁消去分数。
いろいろと考えてみると(10*a+c)/(10*c+b)という形式しかありえない。
というわけで(10*a+c)/(10*c+b)=a/bという方程式を解くことになる。

% echo {1..9}\ {1..9}\ {1..9}$'\n' | awk '$1<$2{if(($1$3)*$2==$1*($3$2))print ($1$3)"/"($3$2)}' 
16/64
19/95
26/65
49/98

4つ見つかった。あとは約分して分母を計算する。
最大公約数を求めてそれで割れば約分できる。

% echo {1..9}\ {1..9}\ {1..9}$'\n' | awk '$1<$2{if(($1$3)*$2==$1*($3$2)){n*=$1$3;m*=$3$2}}END{k=m;while (m%(m=n));print k/n}' n=1 m=1
100

<Older(,) | Newer(.)> | Recent(/)>> | RDF


WWW を検索 jarp.does.notwork.org を検索

わたなべひろふみ
Key fingerprint = C456 1350 085F A320 C6C8 8A36 0F15 9B2E EB12 3885
Valid HTML 4.01!