SICPの2.2.4 Example: A Picture LanguageをPythonでやってみた...けどできなかったからPythonで絵を描いてみた(||゚Д゚) - 牌語備忘録 - pygoの続き。
やりました、Pythonで(゚Д゚)v
python
#2.2.4 Example: A Picture Language #The picture language #Painters def segments_painter(segment_list): # painter is procedure! return lambda frame:[draw_line( frame_coord_map(frame)(start_segment(segment)), frame_coord_map(frame)(end_segment(segment))) for segment in segment_list] def right_split(painter, n): if n == 0: return painter smaller = right_split(painter, n - 1) return beside(painter, below(smaller, smaller)) def corner_split(painter, n): if n == 0: return painter up = up_split(painter, n - 1) right = right_split(painter, n -1) top_left = beside(up, up) bottom_right = below(right, right) corner = corner_split(painter, n - 1) return beside(below(painter, top_left), below(bottom_right, corner)) def square_limit(painter, n): quarter = corner_split(painter, n) half = beside(flip_horiz(quarter), quarter) return below(flip_vert(half), half) def make_vect(x, y): return [x, y] def xcor_vect(v): return v[0] def ycor_vect(v): return v[1] def add_vect(v1, v2): return make_vect(xcor_vect(v1) + xcor_vect(v2), ycor_vect(v1) + ycor_vect(v2)) def sub_vect(v1, v2): return make_vect(xcor_vect(v1) - xcor_vect(v2), ycor_vect(v1) - ycor_vect(v2)) def scale_vect(s, v): return make_vect(s * xcor_vect(v), s * ycor_vect(v)) def up_split(painter, n): if n == 0: return painter smaller = up_split(painter, n - 1) return below(painter, beside(smaller, smaller)) def rotate270(painter): return transform_painter(painter, make_vect(0.0, 1.0), make_vect(0.0, 0.0), make_vect(1.0, 1.0)) def below(painter1, painter2): return rotate90(beside(rotate270(painter1), rotate270(painter2))) def flip_horiz(painter): return transform_painter(painter, make_vect(1.0, 0.0), make_vect(0.0, 0.0), make_vect(1.0, 1.0)) #segment def start_segment(s): return s[0] def end_segment(s): return s[1] #Transforming and combining painters def transform_painter(painter, origin, corner1, corner2): return lambda frame:painter(make_frame( frame_coord_map(frame)(origin), sub_vect(frame_coord_map(frame)(corner1), frame_coord_map(frame)(origin)), sub_vect(frame_coord_map(frame)(corner2), frame_coord_map(frame)(origin)))) def flip_vert(painter): return transform_painter(painter, make_vect(0.0, 1.0), # new origin make_vect(1.0, 1.0), # new end of edge1 make_vect(0.0, 0.0)) # new end of edge2 def shrink_to_upper_right(painter): return transform_painter(painter, make_vect(0.5, 0.5), make_vect(1.0, 0.5), make_vect(0.5, 1.0)) def rotate90(painter): return transform_painter(painter, make_vect(1.0, 0.0), make_vect(1.0, 1.0), make_vect(0.0, 0.0)) def squash_inwards(painter): return transform_painter(painter, make_vect(0.0, 0.0), make_vect(0.65, 0.35), make_vect(0.35, 0.65)) def beside(painter1, painter2): split_point = make_vect(0.5, 0.0) paint_left = transform_painter(painter1, make_vect(0.0, 0.0), split_point, make_vect(0.0, 1.0)) paint_right = transform_painter(painter2, split_point, make_vect(1.0, 0.0), make_vect(0.5, 1.0)) return lambda frame:[paint_left(frame), paint_right(frame)] #Frames def frame(): return make_frame(make_vect(0, 0), make_vect(1, 0), make_vect(0, 1)) def frame_coord_map(frame): return lambda v:add_vect( origin_frame(frame), add_vect(scale_vect(xcor_vect(v), edge1_frame(frame)), scale_vect(ycor_vect(v), edge2_frame(frame)))) def make_frame(origin, edge1, edge2): return [origin, edge1, edge2] def origin_frame(frame): return frame[0] def edge1_frame(frame): return frame[1] def edge2_frame(frame): return frame[2] #turtle graphics segments = [ [[0.0, 0.0], [0.2, 1.0]], [[0.2, 1.0], [0.3, 0.8]], [[0.3, 0.8], [0.7, 0.8]], [[0.7, 0.8], [0.8, 1.0]], [[0.8, 1.0], [1.0, 0.0]], [[0.4, 0.6], [0.3, 0.6]], [[0.3, 0.6], [0.3, 0.5]], [[0.3, 0.5], [0.4, 0.5]], [[0.8, 0.6], [0.7, 0.6]], [[0.7, 0.6], [0.7, 0.5]], [[0.7, 0.5], [0.8, 0.5]], [[0.7, 0.4], [0.4, 0.4]], [[0.4, 0.4], [0.4, 0.3]] ] def draw_line(p1, p2): def t(z): return (200 * z) - 1 draw_turtle([[t(p1[0]), t(p1[1])], [t(p2[0]), t(p2[1])]]) import turtle def draw_turtle(linelist): count = 0 for v in linelist: if count % 2: turtle.down() else: turtle.up() count += 1 turtle.goto(v[0], v[1]) def main(): turtle.clear() turtle.tracer(False) turtle.color(1.0, 0.0, 0.0) square_limit(lambda x:segments_painter(segments)(x), 4)(frame()) if __name__ == "__main__": main()
結果
やった(・∀・)やったよ!できました(゚Д゚)b
『関数型言語の勉強にSICPを読もう - (18) 2章 - データによる抽象の構築 - 2.2.4 図形言語 解説とソース - Higepon’s blog』さん大変参考になりました。ありがとうございました。感謝です。