2010-03-21
10種類の記号で書くPerlワンライナーの作り方
java-ja温泉にて、Pythonのワンライナーがキモいという話が出ていて、Perlだってこれくらいキモいの書けるよ!とアピールしてみた
perl -e '""!~("(?{".("{^(?)!(?^{^^!){.^^~~?}{!~}^}^.(!~}!..^^!~}!~~.~^}"^"^}((~))~~^{.{^~?}^!^}(~{^)?()^)^!).^}!()){.^)(}.("^"!~!{}(!(!~((}}!})!^^{^){(.?}{}!~{^~!)^?..(~)!~.?."^"{{?}^(~)~^!..~)??){^.~){.~(!{.)}}^.}^~}?}.^}(^?{~"^".)^!?^(.)!~!)~{^{(}){?!^.~)({?)(^.^!.^{((^!!^(^(!"^"!})^?}^(?^(~{.)(}})!.?^~!!{~))}({^^!..)^^~?{.?)..")."})")'
- "
- {
- }
- (
- )
- ^
- ?
- !
- ~
- .
の、実質10種類の記号だけで書くFizzBuzzワンライナー。
作り方は、Perlの記号化の常套手段である"排他的論理和で作成した文字列を拡張正規表現でevalする"だけ。以下が詳しいです
ある程度の種類の記号を使えば2~3文字くらいの組み合わせで[\x00-\x7F]の文字が作れるのだけど、6文字組み合わせれば上記の記号(ダブルクォートは除外)だけでも128種類全部作れるようだ。[\x80-\xFF]の範囲は単純にビット反転してやればOK。
で、作って繋げてevalさせるようにして(これはしなくても大丈夫なのかも。よくわかってない)拡張正規表現の構文にあてはめてワンライナー形式で出力させる。
出来たのが以下。引数に指定したPerlプログラムを記号ワンライナー化します。
#!/usr/bin/perl use strict; use warnings; use File::Slurp; use List::Util qw/shuffle/; my @chr = qw/ ! ~ ( ) ? { } ^ . /; my %hash = (); for my $c1 (@chr) { for my $c2 (@chr) { for my $c3 (@chr) { for my $c4 (@chr) { for my $c5 (@chr) { for my $c6 (@chr) { my $chr = $c1 ^ $c2 ^ $c3 ^ $c4 ^ $c5 ^ $c6; $hash{$chr} ||= []; push @{ $hash{$chr} }, [ $c1, $c2, $c3, $c4, $c5, $c6 ]; } } } } } } sub symbolize_ascii { my $ascii = shift; my @strings; for my $chr (split //, $ascii) { my @arr = shuffle @{ shuffle @{$hash{$chr}} }; for (0 .. 5) { $strings[$_] .= $arr[$_]; } } return q/("/ . join(q/"^"/, @strings) . q/")/; } my $filetext = read_file(shift); my $to_escape = quotemeta q/"$@{}\\/; $filetext =~ s{ [$to_escape] } {\\$&}xmsg; $filetext = qq/eval"$filetext"/; $filetext =~ s{ [\x00-\x7F]+ } { '.' . symbolize_ascii($&) }xmseg; $filetext =~ s{ [\x80-\xFF]+ } { '.~' . symbolize_ascii(~$&) }xmseg; print qq/perl -e '""!~("(?{"$filetext."})")'/;
$ cat > hoge.pl
print "こんにちは!\n";
$ perl symbolize.pl hoge.pl
perl -e '""!~("(?{".("?{^).(}{{){({"^"{.}{{^.?}~)})"^"~~{^.})!^}~!("^"^^?!)}^)(^{.}"^"(~(?^}({!!^{^"^")}.~.{~^?!)}{").~(")(~~~?~!.)!)?}.))!"^"(?^.}^.(^!~(.!{(?^"^"}){?^{{)^.^~)({?)~"^"~^!{!)){){).{})..~"^"???!(~!{{~~!!)~^))"^"!!)))!?^(?(.~^)^{(").("{!!}{?.."^"^)?..{^^"^"^)^!^{{~"^".~.!(^!)"^"!})!({~~"^"(~).)!^{")."})")'
$ perl -e '""!~("(?{".("?{^).(}{{){({"^"{.}{{^.?}~)})"^"~~{^.})!^}~!("^"^^?!)}^)(^{.}"^"(~(?^}({!!^{^"^")}.~.{~^?!)}{").~(")(~~~?~!.)!)?}.))!"^"(?^.}^.(^!~(.!{(?^"^"}){?^{{)^.^~)({?)~"^"~^!{!)){){).{})..~"^"???!(~!{{~~!!)~^))"^"!!)))!?^(?(.~^)^{(").("{!!}{?.."^"^)?..{^^"^"^)^!^{{~"^".~.!(^!)"^"!})!({~~"^"(~).)!^{")."})")'
こんにちは!
ちゃんと実行できますね。
ちなみに、上記スクリプトそのものを記号ワンライナー化したらこんなんなりました。
Twitterのfollowerをlistに追加するワンライナー
140文字以内に収まるように頑張った結果
perl -MNet::Twitter -e'$t->add_list_member(sugyan,listname,$_)for@{($t=new Net::Twitter traits,[API::Lists,Legacy],netrc,1)->followers_ids}'
add_list_member に渡す引数(上記では sugyan, listname)はハードコード、
指定する名前のlistは作ってあって、.netrcファイルにusernameとpasswordが書いてあるという前提。
machine api.twitter.com login sugyan password ********
あと全然知らなかったのだけど、1つのlistに登録できるのは500ユーザまでらしい。
Page not found | Twitter Developers
ので、followersが500を超えている場合は"followers/ids"でとれるidの最初の500件までしか登録されない。たぶん。
"followers_ids"は5000件くらいまでは一発で取れるようなのでshuffleすれば毎回違うメンバーでlist作れるかも
perl -MList::Util=shuffle -MNet::Twitter -e'$t->add_list_member(sugyan,followingme,$_)for shuffle@{($t=new Net::Twitter traits,[API::Lists,Legacy],netrc,1)->followers_ids}'
2009-11-17
2つのアカウント両方をフォローしているユーザーを数えるワンライナー
@zerna_botと@zenra_bot2の、両方をフォローしているユーザーはどれくらいいるのかと、ふと気になったので久々にワンライナーを書いてみた。
現時点でのそれぞれのフォロワーは
$ perl -MNet::Twitter -le 'print Net::Twitter->new->show_user("zenra_bot")->{followers_count}'
954
$ perl -MNet::Twitter -le 'print Net::Twitter->new->show_user("zenra_bot2")->{followers_count}'
210
これくらい。
これらから重複しているidを抜き出せれば良い。
なんとかTwitterにPOSTできる長さにしようと頑張った結果。
perl -MLWP::Simple -le'++$a{$_}-1&&print for split/\D+/,get($t="http://twitter.com/followers/ids.json?id=zenra_bot").get$t.2'|wc -l
あとで思いついたけど普通にモジュール使ってもそれなりにいける。
perl -MNet::Twitter -le'$t=Net::Twitter->new;++$a{$_}-1&&print for @{$t->followers_ids($z="zenra_bot")},@{$t->followers_ids($z.2)}'|wc -l
前者はjsonデータを繋げた文字列からsplitで数値だけを取り出すという汚いやり方。。後者の方が見るからにスマートではある。
この結果からuserのnameとscreen_nameを取りたいと思ったけどusers/showで1つ1つとっているとAPIを使い切ってしまう。そうなると少ない方のfollowersを取ってきてそれを元に照合していくしかない、、、めんどくさいのでそこまではやらない。
2009-11-04
2009-10-15
Twitterでの自分の発言が1つだけおかしな時間になっている件
$ perl -MJSON -MLWP::Simple -le 'print$$_{created_at}for@{from_json(get"http://twitter.com/statuses/user_timeline/sugyan.json?since_id=4860000000")}'
Thu Oct 15 11:33:40 +0000 2009
Thu Oct 15 11:29:55 +0000 2009
Thu Oct 15 11:19:49 +0000 2009
Thu Oct 15 08:00:14 +0000 2009
Thu Oct 15 05:15:52 +0000 2009
Thu Oct 15 05:08:15 +0000 2009
Thu Oct 15 03:21:32 +0000 2009
Wed Oct 14 23:17:42 +0000 2009
Thu Oct 15 03:16:17 +0000 2009
Thu Oct 15 03:15:30 +0000 2009
Thu Oct 15 02:59:44 +0000 2009
Thu Oct 15 02:52:23 +0000 2009
Thu Oct 15 00:21:52 +0000 2009
Wed Oct 14 14:19:23 +0000 2009
Wed Oct 14 14:18:54 +0000 2009
Wed Oct 14 13:59:23 +0000 2009
Wed Oct 14 13:43:57 +0000 2009
Wed Oct 14 11:56:04 +0000 2009
上から8個目。これは確かにその上下と同じくらいの、今日の昼過ぎに発言したもの(上の数字には時差9時間を加える必要あり)。
23:17:42 +0000 というと午前8時17分。今日は寝坊していたので確実にその時間は寝てました。
何かのバグなのかなーw
2009-09-04
全裸botからみたタイムライン
全裸botはタイムラインの早さに合わせて呟く - すぎゃーんメモという実装はしてみたものの、実際どれくらいの頻度になるのであろうか?
一日の活動をザクッと洗い流してみた。
まずは@zenra_botが@付きの発言(3時間毎の独り言を除外)をしている時間をすべて取得する。
$ perl -MLWP::Simple -MJSON -le 'print $$_{created_at} for grep { $$_{text} =~ /^@/ } @{from_json(get pop)}' 'http://twitter.com/statuses/user_timeline/zenra_bot.json?count=200'
Thu Sep 03 17:00:36 +0000 2009
Thu Sep 03 16:38:53 +0000 2009
Thu Sep 03 16:23:26 +0000 2009
Thu Sep 03 16:08:09 +0000 2009
Thu Sep 03 15:57:51 +0000 2009
Thu Sep 03 15:44:33 +0000 2009
Thu Sep 03 15:29:14 +0000 2009
Thu Sep 03 15:19:57 +0000 2009
Thu Sep 03 15:09:44 +0000 2009
Thu Sep 03 14:58:28 +0000 2009
Thu Sep 03 14:49:15 +0000 2009
Thu Sep 03 14:43:06 +0000 2009
Thu Sep 03 14:36:43 +0000 2009
Thu Sep 03 14:30:33 +0000 2009
Thu Sep 03 14:24:24 +0000 2009
Thu Sep 03 14:11:29 +0000 2009
Thu Sep 03 14:02:17 +0000 2009
Thu Sep 03 13:55:07 +0000 2009
Thu Sep 03 13:47:58 +0000 2009
Thu Sep 03 13:40:49 +0000 2009
Thu Sep 03 13:32:36 +0000 2009
Thu Sep 03 13:22:11 +0000 2009
Thu Sep 03 13:13:00 +0000 2009
Thu Sep 03 13:01:47 +0000 2009
Thu Sep 03 12:52:37 +0000 2009
Thu Sep 03 12:43:24 +0000 2009
Thu Sep 03 12:34:12 +0000 2009
Thu Sep 03 12:25:01 +0000 2009
Thu Sep 03 12:12:40 +0000 2009
Thu Sep 03 12:01:28 +0000 2009
Thu Sep 03 11:50:15 +0000 2009
Thu Sep 03 11:37:53 +0000 2009
Thu Sep 03 11:27:39 +0000 2009
Thu Sep 03 11:18:28 +0000 2009
Thu Sep 03 11:06:14 +0000 2009
Thu Sep 03 10:52:10 +0000 2009
Thu Sep 03 10:40:34 +0000 2009
Thu Sep 03 10:29:15 +0000 2009
Thu Sep 03 10:19:04 +0000 2009
Thu Sep 03 10:05:50 +0000 2009
Thu Sep 03 09:50:30 +0000 2009
Thu Sep 03 09:29:59 +0000 2009
Thu Sep 03 09:14:30 +0000 2009
Thu Sep 03 09:03:16 +0000 2009
Thu Sep 03 08:50:54 +0000 2009
Thu Sep 03 08:37:39 +0000 2009
Thu Sep 03 08:24:17 +0000 2009
Thu Sep 03 08:11:01 +0000 2009
Thu Sep 03 07:54:44 +0000 2009
Thu Sep 03 07:33:19 +0000 2009
Thu Sep 03 07:16:00 +0000 2009
Thu Sep 03 06:57:16 +0000 2009
Thu Sep 03 06:46:03 +0000 2009
Thu Sep 03 06:33:43 +0000 2009
Thu Sep 03 06:01:04 +0000 2009
Thu Sep 03 05:36:38 +0000 2009
Thu Sep 03 05:14:09 +0000 2009
Thu Sep 03 04:51:44 +0000 2009
Thu Sep 03 04:32:00 +0000 2009
Thu Sep 03 04:13:40 +0000 2009
Thu Sep 03 03:58:22 +0000 2009
Thu Sep 03 03:45:05 +0000 2009
Thu Sep 03 03:31:50 +0000 2009
Thu Sep 03 03:17:28 +0000 2009
Thu Sep 03 03:02:10 +0000 2009
Thu Sep 03 02:43:50 +0000 2009
Thu Sep 03 02:23:15 +0000 2009
Thu Sep 03 02:00:32 +0000 2009
Thu Sep 03 01:42:57 +0000 2009
Thu Sep 03 01:22:35 +0000 2009
Thu Sep 03 00:59:10 +0000 2009
Thu Sep 03 00:42:46 +0000 2009
Thu Sep 03 00:24:27 +0000 2009
Thu Sep 03 00:05:06 +0000 2009
Wed Sep 02 23:43:41 +0000 2009
Wed Sep 02 23:26:22 +0000 2009
Wed Sep 02 23:04:59 +0000 2009
Wed Sep 02 22:00:29 +0000 2009
Wed Sep 02 20:07:27 +0000 2009
Wed Sep 02 18:57:23 +0000 2009
Wed Sep 02 17:42:33 +0000 2009
Wed Sep 02 16:47:17 +0000 2009
Wed Sep 02 16:06:26 +0000 2009
Wed Sep 02 15:31:37 +0000 2009
Wed Sep 02 15:29:49 +0000 2009
Wed Sep 02 15:06:43 +0000 2009
Wed Sep 02 14:43:37 +0000 2009
Wed Sep 02 14:20:34 +0000 2009
Wed Sep 02 13:57:31 +0000 2009
Wed Sep 02 13:34:26 +0000 2009
Wed Sep 02 13:11:07 +0000 2009
Wed Sep 02 12:48:04 +0000 2009
Wed Sep 02 12:25:00 +0000 2009
Wed Sep 02 12:01:56 +0000 2009
Wed Sep 02 11:38:54 +0000 2009
Wed Sep 02 11:15:52 +0000 2009
Wed Sep 02 10:52:49 +0000 2009
Wed Sep 02 10:29:47 +0000 2009
Wed Sep 02 10:06:45 +0000 2009
Wed Sep 02 09:43:42 +0000 2009
Wed Sep 02 09:20:40 +0000 2009
Wed Sep 02 08:57:37 +0000 2009
Wed Sep 02 08:34:35 +0000 2009
Wed Sep 02 08:11:33 +0000 2009
Wed Sep 02 07:48:28 +0000 2009
Wed Sep 02 07:25:26 +0000 2009
Wed Sep 02 07:02:23 +0000 2009
Wed Sep 02 06:39:21 +0000 2009
Wed Sep 02 06:16:18 +0000 2009
Wed Sep 02 05:53:15 +0000 2009
Wed Sep 02 05:30:12 +0000 2009
Wed Sep 02 05:07:10 +0000 2009
Wed Sep 02 04:44:08 +0000 2009
Wed Sep 02 04:21:06 +0000 2009
Wed Sep 02 03:58:04 +0000 2009
Wed Sep 02 03:35:01 +0000 2009
Wed Sep 02 03:11:26 +0000 2009
...
…となる。
日本時間との時差もあるし、実際にある発言と次の発言の間がどれくらいの間隔になっているのか分かりにくいのでさらに編集。
$ perl -MLWP::Simple -MJSON -le 'print $$_{created_at} for grep { $$_{text} =~ /^@/ } @{from_json(get pop)}' 'http://twitter.com/statuses/user_timeline/zenra_bot.json?count=200' | perl -MDate::Parse -lne 'print scalar localtime $a, " - ", ($a - ($b = str2time $_)); $a = $b'
Thu Jan 1 09:00:00 1970 - -1251997236
Fri Sep 4 02:00:36 2009 - 1303
Fri Sep 4 01:38:53 2009 - 927
Fri Sep 4 01:23:26 2009 - 917
Fri Sep 4 01:08:09 2009 - 618
Fri Sep 4 00:57:51 2009 - 798
Fri Sep 4 00:44:33 2009 - 919
Fri Sep 4 00:29:14 2009 - 557
Fri Sep 4 00:19:57 2009 - 613
Fri Sep 4 00:09:44 2009 - 676
Thu Sep 3 23:58:28 2009 - 553
Thu Sep 3 23:49:15 2009 - 369
Thu Sep 3 23:43:06 2009 - 383
Thu Sep 3 23:36:43 2009 - 370
Thu Sep 3 23:30:33 2009 - 369
Thu Sep 3 23:24:24 2009 - 775
Thu Sep 3 23:11:29 2009 - 552
Thu Sep 3 23:02:17 2009 - 430
Thu Sep 3 22:55:07 2009 - 429
Thu Sep 3 22:47:58 2009 - 429
Thu Sep 3 22:40:49 2009 - 493
Thu Sep 3 22:32:36 2009 - 625
Thu Sep 3 22:22:11 2009 - 551
Thu Sep 3 22:13:00 2009 - 673
Thu Sep 3 22:01:47 2009 - 550
Thu Sep 3 21:52:37 2009 - 553
Thu Sep 3 21:43:24 2009 - 552
Thu Sep 3 21:34:12 2009 - 551
Thu Sep 3 21:25:01 2009 - 741
Thu Sep 3 21:12:40 2009 - 672
Thu Sep 3 21:01:28 2009 - 673
Thu Sep 3 20:50:15 2009 - 742
Thu Sep 3 20:37:53 2009 - 614
Thu Sep 3 20:27:39 2009 - 551
Thu Sep 3 20:18:28 2009 - 734
Thu Sep 3 20:06:14 2009 - 844
Thu Sep 3 19:52:10 2009 - 696
Thu Sep 3 19:40:34 2009 - 679
Thu Sep 3 19:29:15 2009 - 611
Thu Sep 3 19:19:04 2009 - 794
Thu Sep 3 19:05:50 2009 - 920
Thu Sep 3 18:50:30 2009 - 1231
Thu Sep 3 18:29:59 2009 - 929
Thu Sep 3 18:14:30 2009 - 674
Thu Sep 3 18:03:16 2009 - 742
Thu Sep 3 17:50:54 2009 - 795
Thu Sep 3 17:37:39 2009 - 802
Thu Sep 3 17:24:17 2009 - 796
Thu Sep 3 17:11:01 2009 - 977
Thu Sep 3 16:54:44 2009 - 1285
Thu Sep 3 16:33:19 2009 - 1039
Thu Sep 3 16:16:00 2009 - 1124
Thu Sep 3 15:57:16 2009 - 673
Thu Sep 3 15:46:03 2009 - 740
Thu Sep 3 15:33:43 2009 - 1959
Thu Sep 3 15:01:04 2009 - 1466
Thu Sep 3 14:36:38 2009 - 1349
Thu Sep 3 14:14:09 2009 - 1345
Thu Sep 3 13:51:44 2009 - 1184
Thu Sep 3 13:32:00 2009 - 1100
Thu Sep 3 13:13:40 2009 - 918
Thu Sep 3 12:58:22 2009 - 797
Thu Sep 3 12:45:05 2009 - 795
Thu Sep 3 12:31:50 2009 - 862
Thu Sep 3 12:17:28 2009 - 918
Thu Sep 3 12:02:10 2009 - 1100
Thu Sep 3 11:43:50 2009 - 1235
Thu Sep 3 11:23:15 2009 - 1363
Thu Sep 3 11:00:32 2009 - 1055
Thu Sep 3 10:42:57 2009 - 1222
Thu Sep 3 10:22:35 2009 - 1405
Thu Sep 3 09:59:10 2009 - 984
Thu Sep 3 09:42:46 2009 - 1099
Thu Sep 3 09:24:27 2009 - 1161
Thu Sep 3 09:05:06 2009 - 1285
Thu Sep 3 08:43:41 2009 - 1039
Thu Sep 3 08:26:22 2009 - 1283
Thu Sep 3 08:04:59 2009 - 3870
Thu Sep 3 07:00:29 2009 - 6782
Thu Sep 3 05:07:27 2009 - 4204
Thu Sep 3 03:57:23 2009 - 4490
Thu Sep 3 02:42:33 2009 - 3316
Thu Sep 3 01:47:17 2009 - 2451
Thu Sep 3 01:06:26 2009 - 2089
Thu Sep 3 00:31:37 2009 - 108
Thu Sep 3 00:29:49 2009 - 1386
Thu Sep 3 00:06:43 2009 - 1386
Wed Sep 2 23:43:37 2009 - 1383
Wed Sep 2 23:20:34 2009 - 1383
Wed Sep 2 22:57:31 2009 - 1385
Wed Sep 2 22:34:26 2009 - 1399
Wed Sep 2 22:11:07 2009 - 1383
Wed Sep 2 21:48:04 2009 - 1384
Wed Sep 2 21:25:00 2009 - 1384
Wed Sep 2 21:01:56 2009 - 1382
Wed Sep 2 20:38:54 2009 - 1382
Wed Sep 2 20:15:52 2009 - 1383
Wed Sep 2 19:52:49 2009 - 1382
Wed Sep 2 19:29:47 2009 - 1382
Wed Sep 2 19:06:45 2009 - 1383
Wed Sep 2 18:43:42 2009 - 1382
Wed Sep 2 18:20:40 2009 - 1383
Wed Sep 2 17:57:37 2009 - 1382
Wed Sep 2 17:34:35 2009 - 1382
Wed Sep 2 17:11:33 2009 - 1385
Wed Sep 2 16:48:28 2009 - 1382
Wed Sep 2 16:25:26 2009 - 1383
Wed Sep 2 16:02:23 2009 - 1382
Wed Sep 2 15:39:21 2009 - 1383
Wed Sep 2 15:16:18 2009 - 1383
Wed Sep 2 14:53:15 2009 - 1383
Wed Sep 2 14:30:12 2009 - 1382
Wed Sep 2 14:07:10 2009 - 1382
Wed Sep 2 13:44:08 2009 - 1382
Wed Sep 2 13:21:06 2009 - 1382
Wed Sep 2 12:58:04 2009 - 1383
Wed Sep 2 12:35:01 2009 - 1415
Wed Sep 2 12:11:26 2009 - 1383
...
昨日9月3日0:30付近で切り替えを行った。それまでは23分毎に呟くようにしていたのでだいたい23*60=1380秒間隔になっている。
それ以降は夜が明けるに従って間隔が短くなり、昼に一度ピークを迎え、また収まった後、夕方前の集中力が切れる時間帯に再び加速するw あとはまたゆるやかに加速して23:30頃に最高速度に達する。
一日観察するだけでこんなに色々と見えるのは面白いw
フォロワーの増減でまた変わるだろうし、もう少ししてからもう一度計ってみよう。

