• Skip to primary navigation
  • Skip to main content

Algorithm.co.il

  • About
  • Best Posts
  • Origami
  • Older Projects

Fractals in 10 minutes No. 6: Turtle Snowflake

Posted on 2009-08-31 by lorg 8 Comments

I didn’t write this one, but I found it’s simplicity and availability so compelling, I couldn’t just not write about it.
In a reddit post from a while ago, some commenter named jfedor left the following comment:

A little known fact is that you can do the following on any standard Python installation:

from turtle import *
 
def f(length, depth):
   if depth == 0:
     forward(length)
   else:
     f(length/3, depth-1)
     right(60)
     f(length/3, depth-1)
     left(120)
     f(length/3, depth-1)
     right(60)
     f(length/3, depth-1)
 
f(500, 4)

from turtle import * def f(length, depth): if depth == 0: forward(length) else: f(length/3, depth-1) right(60) f(length/3, depth-1) left(120) f(length/3, depth-1) right(60) f(length/3, depth-1) f(500, 4)

If you copy paste, it’s a fractal in less than a minute. If you type it yourself, it’s still less than 10. And it’s something you can show a kid. I really liked this one.

Filed under: computer science, Fractals, Python

Reader Interactions

Comments

  1. Beni Cherniavsky says

    2009-10-28 at 3:03 am

    Cool!
    I remember doing similar fractals as execin SICP
    [ http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4 ]
    which takes a functional approach.
    So I couldn’t resist to try rewriting it:
    [python]
    def snowflake(length, line=forward, *rest):
    line(length/3, *rest)
    right(60)
    line(length/3, *rest)
    left(120)
    line(length/3, *rest)
    right(60)
    line(length/3, *rest)
    [/python]

    Then try:

    [python]
    snowflake(400)
    snowflake(400, snowflake)
    snowflake(400, snowflake, snowflake)
    [/python]

    etc.

    The purpose of the exercise was to get away from recursion with terminating condition.
    Recursion is cool, but there is a constructive process here that I want to capture directly:
    Draw the _/\_ shape, but use $subshape instead of straight lines.

    But of course “line=forward, *rest” is way too much magic for a newbie.

    “snowflake(400, lambda length: snowflake(length))” is even worse.

    So, how can I nicely capture the construction without recursion? Aha!

    [python]
    def snowflake(length):
    yield length/3
    right(60)
    yield length/3
    left(120)
    yield length/3
    right(60)
    yield length/3

    for a in snowflake(400):
    for b in snowflake(a):
    forward(b)
    [/python]

    What do you think of this?
    It’s as close as Python gets to code blocks – a function with fill-in spaces, “do this where I said yield”.
    Can this work better then recursion for newbies?
    Can we explain yield/for simply enough?

    [I suspect people who know some programming would be more daunted than newbies, because yield is powerful and strange – but newbies don’t have to know that :-]

    P.S. http://mathworld.wolfram.com/KochSnowflake.html

    Reply
  2. Beni Cherniavsky says

    2009-10-28 at 3:05 am

    p.s. I don’t know if WordPress can be configured that way,
    but in a Pythonic blog, you really want to preserve whitespace in comments.

    Reply
  3. lorg says

    2009-10-28 at 1:42 pm

    1. I fixed the python bits in your comment. Writing Python in comments is easy: just add [ python ] and [ / python ] blocks (just without the spaces).

    2. What you suggest is very reminiscent of lstrings, check out http://www.algorithm.co.il/blogs/index.php/projects/lstrings/ , and older fractal links in my blog for more info.

    I’m not sure if it’s clearer than recursion. If presented correctly, recursion may be very intuitive. It might even be explained intuitively using this example! It works much better than sorting :)
    Regarding usage of yield – I’d rather avoid it I think, because then you have to do a lot of hand waving to explain it to newbies (you can’t be accurate).

    By the way, I really liked the line=forward trick. Maybe the names should be different or the *rest should be changed, but it really explains the idea behind the recursion.

    Reply
  4. Chris Wong says

    2012-03-31 at 12:44 am

    Hey, I came up with some very similar code a few days ago:

    def koch(depth, size):
        if depth == 0:
            forward(size)
        else:
            recurse = lambda: koch(depth-1, size/3)
            recurse()
            left(60)
            recurse()
            right(120)
            recurse()
            left(60)
            recurse()
     
    koch(3, 3**4)

    def koch(depth, size): if depth == 0: forward(size) else: recurse = lambda: koch(depth-1, size/3) recurse() left(60) recurse() right(120) recurse() left(60) recurse() koch(3, 3**4)

    Guess all that Haskell trained me well :)

    Reply
  5. mukes says

    2013-04-27 at 6:55 pm

    don’t get it, where to paste it? i pasted it in the terminal as well as in a file.. there’s no output at all.. what am i doin’ wrong, please? i’m new on python and familiar mostly to delphi, so i wonder how it can be drawn, because there seems to be no routine of drawing..?

    Reply
  6. Yehuda Katz says

    2018-09-11 at 12:31 am

    I’m not afraid of recursion, as my following program uses only basic methods. Here it is:
    [python]
    from turtle import *

    ht(); speed(0)

    def fractal(length, depth):
    if depth < 1: fd(length) # base case
    else:
    fractal(length, depth-1); rt(60)
    fractal(length, depth-1); lt(120)
    fractal(length, depth-1); rt(60)
    fractal(length, depth-1)

    for i in range(6): # closing the flake
    fractal(5, 3); rt(60)
    [/python]

    Reply

Leave a Reply Cancel reply

© 2022 Algorithm.co.il - Algorithms, for the heck of it