2008年4月5日土曜日

Python: ワンライナーでマンデルブロ集合を描く

このブログ記事をはてなブックマークに追加

Pythonでマンデルブロ集合(Mandelbrot Set)を描いてみた。ただ、描くだけではつまらないので、ワンライナー(1行プログラム)で書いてみた。Pythonでワンライナーってのは邪悪以外のナニモノでもないと思うので、まともな方はまねしないほうがいいかと。

ワンライナーにしたと云ってもスクラッチからではなく、Python FAQで有名なワンライナーのマンデルブロ集合を流用させてもらった。ただ、オリジナルのものはアスキー文字で表現していたのでPython Imaging Library (PIL)を利用してグラフィカルなものに修正した。もし、PILが入っていないようなら、それはPythonistaの名折れだと思う。コマンドラインで以下の通りに実行すればOK。

python -c "import Image,math;im=Image.new('L',(480,480));im.fromstring((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y>=4.0)or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(256-int(math.sqrt(F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i))*256/math.sqrt(i))),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy))))(0.383,0.384,0.2337,0.2347,800,480,480));im.save('m.gif');im.show()"

これで、最初に示した画像を画面に出力し、m.gifという画像ファイルを同時に作成する。後ろの方の引数を(-2.1,0.7,-1.4,1.4,256,480,480)に変更すれば、左に示す全体像を出力する。

子供のころ、コンピュータの能力をフルに使って数学の深遠な真理を描いているように見えたマンデルブロ集合は憧れだったんだよなぁ。きっとものすごい難しいことをしているんだと想像したものだけど、実際に計算させるのは簡単なんだよね。

追記: 上記のコードだけだとちょっと不親切だと思ったので、もう少しわかりやすい(ワンライナーではない)コードも書いておく。出力結果は同じ。

import Image, math Ru, Ro, Iu, Io, IM, Sx, Sy = 0.383, 0.384, 0.2337, 0.2347, 800, 480, 480 #Ru, Ro, Iu, Io, IM, Sx, Sy = -2.1, 0.7, -1.4, 1.4, 256, 480, 480 def mandelbrot(x, y, IM): c, z, i = complex(x, y), complex(0, 0), 0 while abs(z**2) < 4.0 and i < IM: z = z**2 + c i += 1 return 256 - int(math.sqrt(i) * 256 / math.sqrt(IM)) im = Image.new("L", (Sx, Sy)) im.putdata([mandelbrot(Ru + (x / float(Sx)) * (Ro - Ru), Iu + (y / float(Sy)) * (Io - Iu), IM) for y in range(Sy) for x in range(Sx)]) im.save("m.gif") im.show()

0 コメント: