Hatena::ブログ(Diary)

hogeなlog

プロフィール

hogelog

hogelog

小室 直(こむろ すなお)。電気通信大学2003年入学。2010年修士卒業。プログラミングとかしてます。

カレンダー
1984 | 01 |
2006 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
2010 | 01 | 06 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 12 |
2012 | 01 | 04 | 06 |

May 30(Sat), 2009

[] ケンブリッジ大学がどうたらこうたら

Ruby1.9と適当に1.9対応したRuby/kakasimecab-rubyインストールした環境にて。

#!/usr/bin/env ruby
# vim: set fileencoding=utf-8:

require "kakasi"
require "MeCab"

class Cambridge
    def initialize
	@mecab_y = MeCab::Tagger.new("-Oyomi")
    end
    def hirakana(str)
	node = @mecab_y.parseToNode(str.encode("EUC-JP"))
	result = "".encode("EUC-JP")
	while node do
	    yomi = node.feature.force_encoding("EUC-JP").split(/,/)[5]
	    if yomi=="*"
		surface = node.surface.force_encoding("EUC-JP").encode("EUC-JP")
		yomi = Kakasi.kakasi("-JH -oeuc", surface).force_encoding("EUC-JP")
	    end
	    result += yomi
	    node = node.next
	end
	result
    end
    def wakati(str)
	Kakasi.kakasi("-w -oeuc", str.encode("EUC-JP")).force_encoding("EUC-JP").split
    end
    def cambridge(str)
	wakati(str).map{|w| self.hirakana(w)}.map{|k|
	    if k.size < 4
		k
	    else
		a = k.split(//)
		[a[0], *(a[1..a.size-2].shuffle), a[a.size-1]].join
	    end
	}.join(" ")
    end
end
camb = Cambridge.new
ARGF.each do|line|
    puts camb.cambridge(line)
end
% ruby-1.9.1 cambridge.rb
ケンブリッジ大学がどうたらこうたら
けんっりぶじ だいがく がどうたこらうたら
分かち書きの精度あんまし高くないかも。
わか ち かき の せいど あまんし たかく なかいも 。

そんな遊び。

May 29(Fri), 2009

[] sort_by{rand}はちゃんとshuffleできてるのか

できてるのか。

irb(main):001:0> ([0]*7000).map{(0..6).to_a.sort_by{rand}[0]}.inject([0]*7){|t,i|t[i]+=1;t}
=> [947, 977, 979, 1022, 1021, 1047, 1007]

参考

さらに

k.inaba 2009/05/29 09:34 これも http://chasen.org/~taku/blog/archives/2006/08/schwartzian_tra.html

それっぽい言葉とそれっぽい結果だけで満足してはいけませんね。

普通のshuffleてどんなの。

rubyに組み込みのArray.shuffle
static VALUE
rb_ary_shuffle_bang(VALUE ary)
{
    long i = RARRAY_LEN(ary);

    rb_ary_modify(ary);
    while (i) {
        long j = rb_genrand_real()*i;
        VALUE tmp = RARRAY_PTR(ary)[--i];
        RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
        RARRAY_PTR(ary)[j] = tmp;
    }
    return ary;
}
Pythonのshuffle
    def shuffle(self, x, random=None, int=int):
        """x, random=random.random -> shuffle list x in place; return None.

        Optional arg random is a 0-argument function returning a random
        float in [0.0, 1.0); by default, the standard random.random.
        """

        if random is None:
            random = self.random
        for i in reversed(range(1, len(x))):
            # pick an element in x[:i+1] with which to exchange x[i]
            j = int(random() * (i+1))
            x[i], x[j] = x[j], x[i]

同じアルゴリズム。sort_by{rand}とかよりこっちの方が簡単じゃないすか。

k.inabak.inaba 2009/05/29 09:34 これも http://chasen.org/~taku/blog/archives/2006/08/schwartzian_tra.html

hogeloghogelog 2009/05/30 00:00 非常にありがたいコメントです!

May 28(Thu), 2009

[][] Javaの復習

しばらく先にJava演習のTAをやるのでJavaの復習をします。Javaというのはしちめんどくさい言語で、Cなら

main(c){while(c=getchar())putchar(c);}

で済むプログラムが

import java.io.*;class C{static{int c;try{InputStream i=new BufferedInputStream(System.in);OutputStream o=new BufferedOutputStream(System.out);while((c=i.read())!=-1)o.write(c);o.flush();}catch(Exception e){}}}

のように非常に冗長になってしまいます。JavaのプログラムはjavacコマンドでコンパイルしてできたC.classファイルのあるところで

C:\ぷろぐらむ書くところ> java C 2>nul

のようにして実行します。2>nulとつけるのを忘れるとプログラム終了時に

Exception in thread "main" java.lang.NoSuchMethodError: main

のようなわけのわからないエラーメッセージを吐くので注意しましょう。

[][] 超適当にkakasi-rubyをruby1.9で使えるように

1.8向けのruby拡張を正しく1.9向けに書きなおす作法がまったくわかってないけど、とりあえず動かすだけ動かしてみました。

http://github.com/hogelog/kakasi-ruby/tree/1.9

irb(main):001:0> require "kakasi"
=> true
irb(main):002:0> Kakasi.kakasi("-JH", "漢字の文章ですので平仮名にしてください。")
=> "かんじのぶんしょうですのでひらがなにしてください。"
irb(main):003:0> RUBY_VERSION
=> "1.9.1"

みたいなことができて嬉しい。出力がEUC-JP決め打ち。-ojisとか与えるとおかしなことになる。

irb(main):011:0>  Kakasi.kakasi("-ojis -JH", "漢字の文章ですので平仮名にしてください。")
=> "\e(I4A;z$NJ8>O$G$9$N$GJ?2>L>$K$7$F$/$@$5$$!#"

追記 そういえばString#force_encodingがあった

こっち使うべきか。

http://doc.loveruby.net/refm/api/view/method/String/i/force_encoding

トラックバック - http://d.hatena.ne.jp/hogelog/20090528

May 14(Thu), 2009

[][][] 鬱陶しいSSH総当たり攻撃をDenyHostsではじく

適当に導入して設定して再起動。

% sudo aptitude install denyhosts
% sudo vim /etc/denyhosts.conf
% sudo /etc/init.d/denyhosts restart

denyhosts.confにした適当な設定。特に触れてないものは書いてない。

PURGE_DENY = 5d
banしたホストをどれくらいの時間で許す(purge)かという設定。「PURGE_DENY =」と書いておくとどれだけ時間が経過しても許さない。
PURGE_THRESHOLD = 0
何回までなら許すか。0(デフォルト値)だと何回でも許す。
BLOCK_SERVICE = ALL
sshdに対して怪しいことしたホストは(tcpwrapper, libwrapをサポートしている)全てのデーモンに無視されるように。
DENY_THRESHOLD_INVALID = 5
存在しないアカウントでのログイン失敗5回でban
DENY_THRESHOLD_VALID = 10
存在するアカウントでのログイン失敗10回でban
DENY_THRESHOLD_ROOT = 1
rootでのログイン失敗1回でban
DAEMON_PURGE = 1d
denyhostsのデーモンが1日おきにBAN解除のチェックする。DAEMON_PURGE = 1dにしてPURGE_DENY = 10mとか設定してしまうと、10分で解除する設定だけどデーモンがそれを1日おきにしかチェックしないので結局1日おきくらいにしか解除されない。
トラックバック - http://d.hatena.ne.jp/hogelog/20090514

May 12(Tue), 2009

[] longlife gc patchを少し試しました。

http://d.hatena.ne.jp/authorNari/20090511/1242054805

ruby-1.9.1-p0で試してみました。そのままの方がruby-1.9.1、patchあてたものをruby-partialとしています。

ao-bench*1の結果。

% time ruby-1.9.1 ao-render.rb >ao.ppm
6:03.64 user 0.012 system 6:03.41 total
% time ruby-partial ao-render.rb >ao.ppm
4:58.58 user 0.000 system 4:58.37

1分くらい速くなっているようです。

htmlcompact*2にPHPのSingle HTML File版日本語マニュアルを*3を処理させた結果。

% time ruby-1.9.1 compacttest.rb php_manual_ja.html php_compact.html
2:01.77 user 0.632 system 2:02.81 total
% time ruby-partial compacttest.rb php_manual_ja.html php_compact.html
2:08.56 user 0.552 system 2:09.02 total

ほぼ変わらず?

参考になるのかならないのか、ruby-1.9.1-p0を-pg付きでビルドしてao-bench、htmlcompactをやったときの結果があります。

http://konbu.s13.xrea.com/lib/ruby/ao-render-gprof.log.bz2

http://konbu.s13.xrea.com/lib/ruby/compact_php_man-gprof.log.bz2

GCにかかった時間だけ見るとGCにかかった時間は

ao-bench
29.8%
htmlcompact
18.1%

でしょうか。

~ % cat /proc/cpuinfo
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 15
model           : 43
model name      : AMD Athlon(tm)64 X2 Dual Core Processor  4600+
stepping        : 1
cpu MHz         : 2411.115
cache size      : 512 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow pni lahf_lm cmp_legacy
bogomips        : 4822.23
clflush size    : 64
power management: ts fid vid ttp

processor       : 1
vendor_id       : AuthenticAMD
cpu family      : 15
model           : 43
model name      : AMD Athlon(tm)64 X2 Dual Core Processor  4600+
stepping        : 1
cpu MHz         : 2411.115
cache size      : 512 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow pni lahf_lm cmp_legacy
bogomips        : 4822.18
clflush size    : 64
power management: ts fid vid ttp

% uname -a
Linux hogehoge 2.6.29-1-686 #1 SMP Fri Apr 17 14:35:16 UTC 2009 i686 GNU/Linux

こんなDebian GNU/Linux環境です。

追記 ao-render.rbについて

コード中でrand使ってるので微妙に結果違ってくるのがちょっと気になる。何回か実行しても(記録してないですが)だいたい同じだったので結果も大幅には違ってこないと思いますけど。実験とかのために再現性ある疑似乱数生成の手法が欲しいけどあるんだろか。

追記2

srandに適当な定数与えればいいんでしたね。呆けてました。

追記3

プログラムの始めでsrand 10としてみた結果。

% time ruby-1.9.1 ao-render.rb >ao1.ppm
6:02.07 user 0.252 system 6:02.07 total
% time ruby-partial ao-render.rb >ao2.ppm
5:01.81 user 0.384 system 5:01.97 total
% cmp ao1.ppm ao2.ppm

同じ結果がちゃんと出ていて60秒も速くなっている。

% time (ruby-1.9.1 -e'GC::Profiler.enable;load("ao-render.rb");GC::Profiler.report(STDERR)' >ao3.ppm 2>ao3.gcreport)
6:05.15 user 1.844 system 6:06.72 total
% time (ruby-partial -e'GC::Profiler.enable;load("ao-render.rb");GC::Profiler.report(STDERR)' >ao4.ppm 2>ao4.gcreport)
5:03.65 user 1.112 system 5:04.55 total
% cmp ao1.ppm ao3.ppm&&cmp ao1.ppm ao4.ppm&&cmp ao2.ppm ao3.ppm&&cmp ao3.ppm ao4.ppm
%
% cat ao3.gcreport # ruby-1.9.1
GC 164213 invokes.
Index    Invoke Time(sec)       Use Size(byte)     Total Size(byte)         Total Object                    GC Time(ms)
    1               0.004               216740               344064                17199         3.99999999999999911182
...
164212             364.347              8313340              8339456               416871        44.00300000000773081865
% cat ao4.gcreport # ruby-partial
GC 69520 invokes.
Index    Invoke Time(sec)       Use Size(byte)     Total Size(byte)         Total Object                    GC Time(ms)
    1               0.004               217240               311296                15561         0.00000000000000000000
...
69520             303.363              2940460              3014656               150696        12.00000000001061373212
% ruby-1.9.1 -e 'sum=0.0;ARGF.each{|line|sum += (line=~/([\d.]+)$/ ? $1.to_f : 0.0)};p sum' ao3.gcreport
132316.195000496
% ruby-1.9.1 -e 'sum=0.0;ARGF.each{|line|sum += (line=~/([\d.]+)$/ ? $1.to_f : 0.0)};p sum' ao4.gcreport
67312.1810001647
処理系GC回数総GC時間(ms)平均GC時間(ms)
1.9.1-p0164212132316.1950.80576
longlife-partial6952067312.1810.96824

ですかね。ao-benchはとにかく浮動小数点数演算をしまくるので、Floatのオブジェクトを作りまくってGCしまくります。ささださんの「Ruby処理系での軽量な浮動小数点数表現」*4を導入したらまた相当違ってくると思いますけど。

authorNariauthorNari 2009/05/12 09:14 ありがとうございます.1分も早くなったんですか..ほぇぇ.
GCの時間を計る為にGC::Profilerというモジュールがあります.
ruby -e "GC::Proflier.enable; eval(IO.read(hoge.rb)); GC::Profiler.report"
で出力してくれるかなーと思います.

hogeloghogelog 2009/05/12 14:21 活用させていただきました。でも
eval(IO.read("hoge.rb"))

-e:1:in `eval': invalid character (ArgumentError)
from (eval):293:in `block (2 levels) in render'
from (eval):254:in `times'
from (eval):254:in `block in render'
from (eval):253:in `times'
from (eval):253:in `render'
from (eval):308:in `<main>'
from -e:1:in `eval'
from -e:1:in `<main>'
とか言って落ちたのでloadでやりました。

authorNariauthorNari 2009/05/12 19:12 おぉ,すいません…

May 05(Tue), 2009

[][] luaでpit

Pitは細々としたスクリプトのパスワード管理の面倒さから解放してくれますが、luaのpit実装が見当たらなかったので書いてみました。

http://github.com/hogelog/luapit/tree/master

luayamlをインストールして、pit.luaをダウンロードして/usr/share/lua/5.1/とかそのあたりにコピーして、コード中で

require "pit"
account = pit.get("twitter", {username="id or email",password="password"})

-- account.usernameとかaccount.passwordを使ったコード

みたいに使えると思います。

luaYAMLのインストール

なんかdebianのunstableでluaYAMLが微妙にインストールめんどうだったのでメモ。これはsyckのluaバインディングなのですが、

$ sudo aptitude install libsyck0-dev

で入れたsyckだとluayamlのテストに通らなかったので自分でビルドしたsyckを使ってみた。

$ wget http://rubyforge.org/frs/download.php/4492/syck-0.55.tar.gz
$ tar zxf syck-0.55.tar.gz
$ cd syck-0.55
$ ./configure
$ make
$ gcc -o syck.so -shared syck.c -lsyck -L./sick-0.55/lib -I/usr/include/lua5.1/
$ cp -f syck.so /usr/lib/lua/5.1

などとしたらtest.luaも通った。たぶん普通に使えている。

トラックバック - http://d.hatena.ne.jp/hogelog/20090505

May 04(Mon), 2009

[] pitってこういう感じでしたっけね。

すごく適当だけど眠くてこのまま放置したまま数年とか経ちそうなので貼っておいてみる。luayaml使ってる。

トラックバック - http://d.hatena.ne.jp/hogelog/20090504
最近のコメント