Треугольники Серпинского с использованием черепахи и рекурсивной функции - PullRequest
0 голосов
/ 02 июня 2018

Я пытаюсь понять рекурсивные функции, они выглядят так сложно.Единственное, что я до сих пор понял, это то, что они должны быть базовым вариантом и основаны на доказательстве индукции.То, как программисты думают о простом базовом случае, выходит за рамки мысли до сих пор.Примеры фракталов были решены в книге с использованием только одной строки базового случая.И здесь, в треугольниках Серпинского, мне нужно было так много строк кода.Ну, теперь я близок к этому, но все еще вне досягаемости.Ниже приведен код, который работает для порядков 0 и 1, но для более высоких порядков добавляет больше места.Я знаю, что это не питонский код, но это лучшее, что я мог бы написать.

import math, turtle

window=turtle.Screen()
window.title('Sierpinski')
window.bgcolor('lightblue')

alex=turtle.Turtle()

def sierpinski(a,t,size):
    if a==0:
        for i in range(3):
            t.forward(size)
            t.left(120)
    else:
       sierpinski(a-1,t,size/3)
       t.forward(size/3)
       sierpinski(a-1,t,size/3)
       t.forward(size/3)
       t.left(120)
       t.forward(size/3)
       sierpinski(a-1,t,size/3)
       t.forward(size/3)
       t.left(120)
       t.forward(size*2/3)
       t.left(120)

sierpinski(3,alex,200)

window.mainloop()

Да, это немного долго, я все еще не ясно в своем мыслительном процессе

  1. Кто-нибудь может объяснить, что не так с моим кодом?
  2. Как его можно сделать более пифоническим?

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Мы можем сделать функцию sierpinski() проще и быстрее, используя штамповку вместо рисование :

from turtle import Turtle, Screen

CURSOR_SIZE = 20

def sierpinski(depth, turtle, size):

    turtle.shapesize(size / CURSOR_SIZE)
    turtle.stamp()

    if depth < 1:
        return

    half = size / 2
    circumradius = half * 3 ** 0.5 / 3

    for _ in range(3):
        turtle.forward(circumradius)  # to
        sierpinski(depth - 1, turtle, half)
        turtle.backward(circumradius)  # and fro
        turtle.left(120)

window = Screen()
window.mode('logo')  # make 0 degrees straight up
window.title('Sierpinski')
window.bgcolor('lightblue')

alex = Turtle('triangle')
alex.fillcolor(window.bgcolor())
alex.penup()

sierpinski(3, alex, 300)

alex.hideturtle()
window.mainloop()

Это также имеет преимущество рисования треугольникапо центру на экране, а не в сторону.Чертеж может быть дополнительно оптимизирован путем перемещения курсора по кругу вокруг области треугольника вместо перемещения туда-сюда по центру.

0 голосов
/ 02 июня 2018

Хорошо, я нашел, как это сделать с помощью видео , которое дало мне указание разделить его пополам, а не на одну треть.

, поэтому код должен был быть

import math, turtle

window=turtle.Screen()
window.title('Sierpinski')
window.bgcolor('lightblue')

alex=turtle.Turtle()

def sierpinski(a,t,size):
    if a==0:
        for i in range(3):
            t.forward(size)
            t.left(120)

    else:
       sierpinski(a-1,t,size/2)
       t.forward(size/2)
       sierpinski(a-1,t,size/2)
       t.forward(size/2)
       t.left(120)
       t.forward(size/2)
       sierpinski(a-1,t,size/2)
       t.forward(size/2)
       t.left(120)
       t.forward(size)
       t.left(120)

sierpinski(3,alex,200)

window.mainloop()

Но может ли код быть более кратким?

Редактировать

Этого будет достаточно:

def sierpinski(a, t, size):
    half = size / 2
    if a >= 0:
        sierpinski(a-1, t, half)
        t.forward(half)

        sierpinski(a-1, t, half)
        t.forward(half)
        t.left(120)
        t.forward(half)

        sierpinski(a-1, t, half)
        t.forward(half)
        t.left(120)
        t.forward(size)
        t.left(120)

Это работает, потому чтооба блока if end else рисовали треугольники (блок else делал это только для перемещения курсора, но все же), но блок else совершал рекурсивные вызовы.

Чтобы сделать это "более питонический" , вы можете поместить все это в класс:

class SierpinskiTurtle(turtle.Turtle):
    def sierpinski(self, depth, size):
        half = size / 2
        if depth >= 0:
            self.sierpinski(depth-1, half)
            self.forward(half)

            self.sierpinski(depth-1, half)
            self.forward(half)
            self.left(120)
            self.forward(half)

            self.sierpinski(depth-1, half)
            self.forward(half)
            self.left(120)
            self.forward(size)
            self.left(120)

alex = SierpinskiTurtle()

alex.sierpinski(3, 200)
...