牌語備忘録 -pygo

あくまでもメモです。なるべくオフィシャルの情報を参照してください。

牌語備忘録 -pygo

SICP 2.2.4 Example: A Picture LanguageをPythonでやってみたらデキタ━━━━(゚∀゚)━━━━ッ!!

SICP2.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』さん大変参考になりました。ありがとうございました。感謝です。