PythonでMethod Missing
聞くところによると、RubyにはMethod Missingなる機能があるとか。
いわく、オブジェクトにメソッドがない場合に、どういう処理をするかを記述するとか。
こいつぁ、われらがPythonにも欲しい機能です。
上記の文面をまともに受け取る使い方でも良いのですが、たとえば、あるオブジェクトのメソッド全てについて、
同様な処理を付加するといったラッパーが簡単に書けちゃうわけです。
というわけで調べてみた。
そのものずばりは出てこなかったけれど、おおむねこんなかんじ。
Method missing(のようなもの)を使った簡易ラッパー。
import threading import time class Wrappee: def __init__( self, count ): self.count = count def print_something( self, text ): for i in range( self.count ): print( i, " something : ", text ) time.sleep( 0.5 ) class Wrapper: def __init__( self, wrapper ): self.wrappee= wrapper # Emulate ruby like " missing method ". def __getattr__( self, name ): def _method_missing( *args ): return args print( "--", name, " is called --") ret = getattr( self.wrappee, name, _method_missing) return ret wrappee = Wrappee( 10 ) wrapper = Wrapper( wrappee ) wrapper.print_something( " foo " )
ううん、これは便利だ。
ただ、ラップされるオブジェクトに指定の関数名がない場合にエラーが出ないのが玉に傷。
どこかのサイトで関数名一覧をディクショナリでもっておいて検査するという手法も見られたけど、もっと楽にいけないものだろうか。
MacPortsでHugs突っ込むときにコケる件。
トラッカーによるとleopardでは起こらないけどsnow leopardでは起こる。
https://trac.macports.org/ticket/20950
以下を参考にすれば最短距離。
パッチ2つ当てるのみ。
http://antsomerset.co.uk/2010/10/04/installing-hugs98-haskell-on-mac-10-6-snow-leopard/
すごいのみつけた
以前から、Haskellの遅延評価の枠組みは確率分布のサンプリングとかやるのによさそうだなぁとか思っていたのですよ。
再帰を使うってだけなら、C++とかでも上記の式と同様になるかと思いますが、
いざサンプリングするぞって時に面倒なのが、SBPのtailの方。
僕の場合だと、必要な分だけ確率列を用意して、サンプリング中に必要になる、
そのつど確率変数に値を振っていくという形式のコードです。面倒。
んが、Haskellだと(多分)そのへん自動でやってくれる!すごい!
んじゃないのかな。実際動かしたわけじゃないのでわからないのですが。
そんなこんなで、Haskellでノンパラベイズ周辺のライブラリを書こうと意気込んだその矢先、
しかもコードは、かのHal Daume III御大。
とりあえずオープンソースにして。コミットするから。
O'REILLYどうした
もともと翻訳どうよ、と思うものが多い出版社でしたが、
久々の出物、しかも大物、しかも2つ。
あまりに酷いので、ここで血祭りにあげようと思います。
プライムナンバーズ ―魅惑的で楽しい素数の事典 (O’Reilly math series)
- 作者: David Wells,伊知地宏(監訳),さかいなおみ
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/10/25
- メディア: 単行本
- クリック: 15回
- この商品を含むブログ (33件) を見る
数学を生み出す魔法のるつぼ ―実験数学への招待 (O’Reilly math series)
- 作者: Jonathan Borwein,Keith Devlin,伊知地宏
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/12/28
- メディア: 単行本(ソフトカバー)
- クリック: 20回
- この商品を含むブログ (11件) を見る
これはひどすぎる。読めたものではないとはまさにこれか。
分かりにくい日本語とか、そういうレベルではなく、
もはや日本語の体をなしていない文章だらけ。
誤植等も非常に多い。
久々に焚書目録に登録しました。
なお、非常に残念ですが、内容については触れることはできません。
50ページくらいで読むのをやめてしまったので。
そのうち原書のほうを買います。
原著をなぶって遊ぶのはやめたらどうかと声を大にして言いたい。
....追記
プライムナンバーズを無理やり読んでみた。
普通に原書がほしい。
Project Euler Problem 84
モノポリーで、どの升目に止まりやすいかという問題。
まじめに計算できそうな感じだけど、せっかくなのでサンプリングしてみる。
ただひたすら面倒なだけ。
import random # monopoly simulator cells = [ 'GO', 'A', 'CC', 'A', 'T', 'R', 'B', 'CH', 'B', 'B', 'JAIL', 'C', 'U', 'C', 'C', 'R', 'D', 'CC', 'D', 'D', 'FP', 'E', 'CH', 'E', 'E', 'R', 'F', 'F', 'U', 'F', 'G2J', 'G', 'G', 'CC', 'G', 'R', 'CH', 'H', 'T', 'H' ] cccards = ['DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', 'DC', '0', '10'] ccards = ['DC', 'DC', 'DC', 'DC', 'DC', 'DC', '0', '10', '11', '24', '39', '5', 'G2NR', 'G2NR', 'G2NU', 'GB3'] def pe84(): ntrial = 500000 shuffle_cards() visited = sampling( ntrial ) print visited print get_solution( visited ) def get_solution( visited ): first = get_max_index( visited ) visited[first] = 0 second = get_max_index( visited ) visited[second] = 0 third = get_max_index( visited ) return "".join( [encode_squareface( first ), encode_squareface( second ), encode_squareface( third ) ] ) def get_max_index( lis ): idx = 0 max = 0 for i in range( 0, len( lis ) ): if lis[i] >= max: idx = i max = lis[i] return idx def sampling( ntrial ): visited = [ 0 for i in range(0, len(cells))] pos = 0 tried = 0 # should I count first GO as visited ? while tried < ntrial: nextpos = nextcell( pos) #print len( visited ), " ", nextpos visited[nextpos]+= 1 pos = nextpos tried +=1 return visited def nextcell( current_position): global prev_doubles score1 = random.randint( 1, 4 ) score2 = random.randint( 1, 4 ) if score1 == score2: if prev_doubles == 2: prev_doubles = 0 return 10 else: prev_doubles += 1 else: prev_doubles = 0 next_position = advance( score1+score2, current_position ) #print score, next_position if cells[next_position] == 'CC': return ccjump( next_position ) elif cells[next_position] == 'CH': return cjump( next_position ) elif cells[next_position] == 'G2J': return 10 else: return next_position def ccjump( current_position ): card = drawcc() if card == 'DC': return current_position else: return int( card ) def cjump( current_position ): card = drawc() if card == 'DC': return current_position elif card == 'G2NR': return g2nr( current_position ) elif card == 'G2NU': return g2nu( current_position ) elif card == 'GB3': return back( 3, current_position ) else: return int( card ) def g2nr( current_position ): while( True ): current_position = advance( 1, current_position) if cells[current_position] == 'R': return current_position def g2nu( current_position ): while( True ): current_position = advance( 1, current_position ) if cells[current_position] == 'U': return current_position def advance( nsteps, current_position ): while nsteps > 0: current_position+=1 if current_position > len( cells ) - 1: current_position = 0 nsteps-=1 return current_position def back( nsteps, current_position ): while nsteps > 0: current_position -= 1 if current_position < 0: current_position = len( cells ) - 1 nsteps -=1 return current_position def shuffle_cards(): global ccards global cccards random.shuffle( ccards ) random.shuffle( cccards ) def drawc(): global ccards drawed = ccards.pop( 0 ) ccards.append( drawed ) return drawed def drawcc(): global cccards drawed = cccards.pop( 0 ) cccards.append( drawed ) return drawed def encode_squareface( num ): print "n : ", num if num < 10: return '0'+str(num ) else: return str( num ) prev_doubles = 0 pe84()
なんだかとてもまじめに書いた。
Project Euler Problem 125
単なるブルートフォースなのだが、範囲が違うけど同じ数が出うることと、それを加算してはいけないことに1時間ハマって死にたい。何この凡ミス。
typedef unsigned long long int nat; vector<nat> gensqsq(nat lim){ vector<nat> sqsq; for(nat i=1;i*i <= lim;++i)sqsq.push_back(i*i); return sqsq; } bool ispalindromic( nat n ){ if( n >= 10 && n % 10 == 0 ) return false; deque<int> d; while( n ){ d.push_front( n % 10 ); n /= 10; } for( int i=0, j=d.size()-1; i <= j; ++i, --j ){ if( d[i] != d[j] ) return false; } return true; } nat pe125(){ set<nat> s; nat limit = 100000000; nat total = 0; vector<nat> sq = gensqsq(limit); for( nat from = 0; from < sq.size(); ++from){ nat seqsum = 0; for(nat to=from; to < sq.size(); ++to ){ seqsum += sq[(unsigned int )to]; if( to == from ) continue; if( seqsum >= limit )break; if( ispalindromic( seqsum ) ) s.insert( seqsum ); } } for( set<nat>::iterator itr = s.begin(); itr != s.end(); ++itr ) total += *itr; return total; }
新言語
NTTはもう少しまじめくさいところだと思っていた。
NTTの人が書いたプログラミング言語のhttp://www.brl.ntt.co.jp/people/hirata/Papers/spa99.pdf:論文。
その名も、織田信長。
論文の字面の時点ですでにシュールすぎるが、この言語の真価はその由来にある。
新しい言語 → 新言語 → 信玄後 → 織田信長
ソース:
http://iiyu.asablo.jp/blog/2008/03/14/2741992
http://www.brl.ntt.co.jp/people/hirata/Papers/spa99-on-slides.pdf
NTTのCS研は、自然言語だけでなく計算機言語もすばらしく、
その上ギャグも一流なんですね。
完全に僕の負けです。本当にありがとうございました。
スライスでちょっと考え込んだ
Pythonにて、
s = "123456789"
というようなリスト(この場合文字列だが)で、マイナスのインデックスを指定してスライスすると、末尾から数えてくれる。
print s[-4:-1]
とすれば"678"が取れる。
じゃあマイナスインデックスから、リスト末尾までのスライスはどうすればいいの?
print s[-4:0]
違う違う。
print s[-4:-0]
なんぞこれは。違う。
pythonのスライスの2つ目のargument(何ていうんだ)は"未満"の扱いなので、困る。
どうすればいいんだー。
と悩んで10分。
print s[-4:]
あ、そっか。
インデックス指定できないのは気持ち悪いけど、多分これしかなさそう。
末尾の次の要素、なんてないもんなぁ。これでいいのかpython。
Project Euler 87
ストレートにx^2 + y^3 + z^4を総当りでとけばよい。
どうせそれぞれの変数に入る素数の値候補は多くは無いので、
最初にリストにしてしまって、リストの3重ループで回す。
当然xのとりうる範囲は50000000の平方根より少ない。
yのとりうる範囲は50000000の立方根より少ない。
zのとりうる範囲は50000000の4乗根より少ない。
#project euler 87 use strict; use warnings; use POSIX qw( ceil ); sub isprime{ my $target = $_[0]; return 0 if( $target <= 1 ); return 1 if( $target == 2 ); return 0 if( $target % 2 == 0 ); for( my $i = 3; $i <= ceil( sqrt( $target ) ); $i+=2 ){ if( $target % $i == 0){ return 0; } } return 1; } sub get_primearray{ my $limit = $_[0]; my @prime; return 0 if ( $limit < 1 ); foreach( 1..$limit){ if( isprime( $_ ) == 1 ){ push( @prime, $_ ); } } return @prime; } my $limit = 50000000; my $sq_lim = ceil( $limit ** ( 1 / 2) ); my $cb_lim = ceil( $limit ** ( 1 / 3) ); my $fr_lim = ceil( $limit ** ( 1 / 4) ); print "square : calcurate to $sq_lim\n"; print "cube : calcurate to $cb_lim\n"; print "forth power : calcurate to $fr_lim\n"; my @sqarr = get_primearray( $sq_lim ); my @cbarr = get_primearray( $cb_lim ); my @frarr =get_primearray( $fr_lim ); my %expr; print "for sqare : @sqarr\n"; print "for cube : @cbarr\n"; print "for fourth power : @frarr\n"; foreach my $x(@sqarr){ foreach my $y( @cbarr ){ foreach my $z( @frarr ){ my $key = $x ** 2 + $y ** 3 + $z ** 4; if( $key >= $limit ){ next; } else { $expr{$key} = 1; } } } } my $count = keys( %expr ); print "$count\n";
このあたりの問題の難易度差が激しい気がする。