#!/usr/bin/env python3
from PIL import Image, ImageDraw
from functools import reduce
# ニュートン法はfunctools.reduceを使った方がシンプルに書ける
def newton(x):
return reduce(lambda j, i: j - (j**3 - 1) / (3 * j**2), range(10), x)
def plot(draw, s):
tpl = (255, 0, 0)
# 右辺のtplの「回転結果」のリスト要素は左辺に「構造化代入」される
red, green, blue = [tpl[i:] + tpl[:i] for i in range(3, 0, -1)]
# ローカル関数fooを定義する
def foo(x, y):
# Pythonはマトモなスコープが無いので、ローカル関数から数値等の単項データ
# (この場合はs)を参照出来ないので、nonlocal宣言を使う
nonlocal s
# hs の定義はローカル関数内にあった方がいい(ここ以外では使われていない)
hs = s // 2
z = newton(complex(x - hs + 0.5, -y + hs + 0.5) / s * 4)
# 条件分岐「文」ではなく、条件分岐「式」に慣れよう
return red if z.real > 0 else \
green if z.real < 0 and z.imag > 0 else \
blue
# Pythonではfor文を使うよりリスト内包表記を使った方がスマートだ
[draw.rectangle([x, y, x + 1, y + 1], fill = foo(x, y)) \
for y in range(s) for x in range(s)]
# スクリプトとして起動する
if __name__ == '__main__':
size = 512
img = Image.new('RGB', (size, size))
plot(ImageDraw.Draw(img), size)
img.show()
img.save('img.png')
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoKZnJvbSBQSUwgaW1wb3J0IEltYWdlLCBJbWFnZURyYXcKZnJvbSBmdW5jdG9vbHMgaW1wb3J0IHJlZHVjZQoKIyDjg4vjg6Xjg7zjg4jjg7Pms5Xjga9mdW5jdG9vbHMucmVkdWNl44KS5L2/44Gj44Gf5pa544GM44K344Oz44OX44Or44Gr5pu444GR44KLCmRlZiBuZXd0b24oeCk6CiAgICByZXR1cm4gcmVkdWNlKGxhbWJkYSBqLCBpOiBqIC0gKGoqKjMgLSAxKSAvICgzICogaioqMiksIHJhbmdlKDEwKSwgeCkKCmRlZiBwbG90KGRyYXcsIHMpOgogICAgdHBsID0gKDI1NSwgMCwgMCkKICAgICMg5Y+z6L6644GudHBs44Gu44CM5Zue6Lui57WQ5p6c44CN44Gu44Oq44K544OI6KaB57Sg44Gv5bem6L6644Gr44CM5qeL6YCg5YyW5Luj5YWl44CN44GV44KM44KLCiAgICByZWQsIGdyZWVuLCBibHVlID0gW3RwbFtpOl0gKyB0cGxbOmldIGZvciBpIGluIHJhbmdlKDMsIDAsIC0xKV0KICAgICMg44Ot44O844Kr44Or6Zai5pWwZm9v44KS5a6a576p44GZ44KLCiAgICBkZWYgZm9vKHgsIHkpOgogICAgICAgICMgUHl0aG9u44Gv44Oe44OI44Oi44Gq44K544Kz44O844OX44GM54Sh44GE44Gu44Gn44CB44Ot44O844Kr44Or6Zai5pWw44GL44KJ5pWw5YCk562J44Gu5Y2Y6aCF44OH44O844K/CiAgICAgICAgIyAo44GT44Gu5aC05ZCI44GvcynjgpLlj4Lnhaflh7rmnaXjgarjgYTjga7jgafjgIFub25sb2NhbOWuo+iogOOCkuS9v+OBhgogICAgICAgIG5vbmxvY2FsIHMKICAgICAgICAjIGhzIOOBruWumue+qeOBr+ODreODvOOCq+ODq+mWouaVsOWGheOBq+OBguOBo+OBn+aWueOBjOOBhOOBhCjjgZPjgZPku6XlpJbjgafjga/kvb/jgo/jgozjgabjgYTjgarjgYQpCiAgICAgICAgaHMgPSBzIC8vIDIKICAgICAgICB6ID0gbmV3dG9uKGNvbXBsZXgoeCAtIGhzICsgMC41LCAteSArIGhzICsgMC41KSAvIHMgKiA0KQogICAgICAgICMg5p2h5Lu25YiG5bKQ44CM5paH44CN44Gn44Gv44Gq44GP44CB5p2h5Lu25YiG5bKQ44CM5byP44CN44Gr5oWj44KM44KI44GGCiAgICAgICAgcmV0dXJuIHJlZCBpZiB6LnJlYWwgPiAwIGVsc2UgXAogICAgICAgICAgICAgICBncmVlbiBpZiB6LnJlYWwgPCAwIGFuZCB6LmltYWcgPiAwIGVsc2UgXAogICAgICAgICAgICAgICBibHVlCiAgICAjIFB5dGhvbuOBp+OBr2ZvcuaWh+OCkuS9v+OBhuOCiOOCiuODquOCueODiOWGheWMheihqOiomOOCkuS9v+OBo+OBn+aWueOBjOOCueODnuODvOODiOOBoAogICAgW2RyYXcucmVjdGFuZ2xlKFt4LCB5LCB4ICsgMSwgeSArIDFdLCBmaWxsID0gZm9vKHgsIHkpKSBcCiAgICAgZm9yIHkgaW4gcmFuZ2UocykgZm9yIHggaW4gcmFuZ2UocyldCgojIOOCueOCr+ODquODl+ODiOOBqOOBl+OBpui1t+WLleOBmeOCiwppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgogICAgc2l6ZSA9IDUxMgogICAgaW1nID0gSW1hZ2UubmV3KCdSR0InLCAoc2l6ZSwgc2l6ZSkpCiAgICBwbG90KEltYWdlRHJhdy5EcmF3KGltZyksIHNpemUpCiAgICBpbWcuc2hvdygpCiAgICBpbWcuc2F2ZSgnaW1nLnBuZycpCg==