Turtle Graphics with Recursion - python

I need to draw a shape using recursion and turtle graphics.
I'm more of a looper and rarely ever use recursion, so some help here with this would be nice. Not even sure where to start.
The shape just needs to be cool looking.

Oh man! What a fun problem :)
As you are a self-proclaimed 'looper', I would think about recursion just as you would looping.
In a for loop, you execute the body of the loop until the for loop condition is satisfied. Now, recursion is very similar. You keep calling the function until the parameters of the function no longer hit a recursive case. They hit a base case instead which then returns a value that the recursion can then build up on.
So thinking about recursion this way, let's think about how to draw a square. You need to first identify what parts of the code get repeated (i.e. what would be in the body of a for loop trying to do the same thing). Then, identify when you want this repetition to stop (i.e. how do I know when a for loop exits).
While drawing a square, I can think of two major things that get repeated at least 4 times. The turtle goes forward a certain number of steps and the turtle turns 90 degrees (or 270 degrees depending on orientation). So this would be something we detail in our recursive case.
Now, let's think about the base case. Well, we know that a square has 4 sides, so after the turtle draws four sides, we want it to stop.
Lastly, let's think about the function declaration and how these two pieces, the recursive case and the base case, play into it. A function declaration may take the following form (in Python):
def draw_square_recursive(turn_deg=90, side_len, sides=4):
"""
Function draws a square with turtle graphics recursively
:param turn_deg: an int, the number of degrees a turtle should turn
:param side_len: an int, the length of a side of the square
:param sides: an int, the number of sides in our square
"""
turn_deg and side_len will be important for our recursive case as they define how a turtle should turn and how far it should 'walk'. sides is an interesting parameter and one we can use to dictate whether to continue recurring or stop. If we subtract 1 from sides every time we draw a side, we will know that we need to stop recurring when sides == 0, a base case!
Thus, whenever we call our function to recur again, we will call it as, draw_square_recursive(side_len, sides-1):
Overall, the structure of the function would look like:
def draw_square_recursive(turn_deg=90, side_len, sides=4):
"""
Function draws a square with turtle graphics recursively
:param turn_deg: an int, the number of degrees a turtle should turn
:param side_len: an int, the length of a side of the square
:param sides: an int, the number of sides in our square
"""
if sides == 0:
# base case!
else:
# recursive case!
Note that this function named draw_square_recursive but it can be much more generalized to other shapes. Do you see how?
Sorry if this was a long winded answer! Hope it helps ;p

Without any parametrization, here a beginning:
import time
from turtle import *
def recurse(n):
if n>0:
left(10)
forward(5)
recurse(n-1)
recurse(20)
time.sleep(5)
When you create recursive function, you need to have a stop criterion that effectively guaranties your program will exit at some point.

More editorial than answer, but recursion like this:
def recurse(n):
if n>0:
left(10)
forward(5)
recurse(n-1)
which is better written as iteration:
for n in range(2):
left(10)
forward(5)
is similar to folks who ask, "How can I count the number of elements in a list using recursion?" Ditto drawing a square using recursion.
I understand the goal is to learn about recursion, but what seems to get lost is that there are times where recursion makes wonderful things happen and times where it just slows down your program. Fractals are an opportunity to so something of wonder with recursion:
import sys
from turtle import Turtle, Screen
def hilbert_curve(n, turtle, angle=90):
if n <= 0:
return
turtle.left(angle)
hilbert_curve(n - 1, turtle, -angle)
turtle.forward(1)
turtle.right(angle)
hilbert_curve(n - 1, turtle, angle)
turtle.forward(1)
hilbert_curve(n - 1, turtle, angle)
turtle.right(angle)
turtle.forward(1)
hilbert_curve(n - 1, turtle, -angle)
turtle.left(angle)
depth = int(sys.argv[1])
size = 2 ** depth
screen = Screen()
screen.setworldcoordinates(0, 0, size, size)
yertle = Turtle('turtle')
yertle.speed('fastest')
yertle.penup()
yertle.goto(0.5, 0.5)
yertle.pendown()
hilbert_curve(depth, yertle)
yertle.hideturtle()
screen.exitonclick()
USAGE
% python3 hilbert.py 5
(PARTIAL) OUTPUT
I'm not picking on the other answers, I'm suggesting you think big (or at least beyond "just needs to be cool looking".)

Related

Varying recursive function at given depth

I have a recursive function drawing a fractal, using the python turtle module:
def fract(t, order, size):
if order == 0:
t.forward(size)
else:
for angle in (60, -120, 60, 0):
fract(t, order - 1, size / 3)
t.left(angle)
I have another function calling the first function and modifying the last angle, so that the fractals build a circle
def circle(t, order, size):
for i in range(order):
fract(t, 2, size)
t.right(360 / order)
circle(t, 4, 300)
While this works as intended, the real goal is to get the same result in a single recursive function.
Obviously this is not a real programming case, but a task from a python beginner's book, which I'm totally stuck with. I suppose the awkward title of the question reflects my lack of understanding the problem.
I agree with the sentiments of #quamrana on this matter, but let's solve what could be a difficult problem. With a bit of trickery.
First, your consolidated function has to take four argument as the order argument to circle() isn't related to the order argument to fract(). We'll rename the first of these to sides() as that's what it represents.
Second, your fract() function isn't completely recursive, it uses iteration internally. I'm going to follow that same pattern in my solution.
Finally, we need a bit of hidden information to work with -- you could use a defaulted fifth argument that changes internally but instead I'm going to play with the type of sides to achieve this result:
import turtle as t
def fract(t, sides, order, size):
if order == 0:
t.forward(size)
elif sides is not None:
for _ in range(sides):
fract(t, None, order, size)
t.right(360 / sides)
else:
for angle in (60, -120, 60, 0):
fract(t, None, order - 1, size / 3)
t.left(angle)
t.speed('fastest') # because I have no patience
fract(t, 4, 2, 300)
t.hideturtle()
t.exitonclick()
I believe this achieves your desired result with minimal change to your original code. In addtion to the fract(t, 4, 2, 300) invocation, which produces your original figure, we can also do variations like fract(t, 3, 3, 300):
The next problem you might want to tackle is how to center these images on the screen so that fract(t, 5, 1, 300) doesn't fall off the edge.
Assuming that your fract() function is supposed to call itself, then I have been able to run your code successfully.
What you have done is to define a recursive function fract() which is called multiple times by your circle() function. This is called composing your functions. This is a good thing.
Each of your functions has closely defined behaviour, that is they are cohesive. This means that other programmers can pick up your functions (especially fract()) and reuse them in their own programs.
My opinion is that it is best to have many small cohesive functions (and classes and modules) which can be combined in many more ways than were originally intended.

Drawing a star on Python using "drawStar"

I have been writing a small code to have my turtle (t) drawing a star. I need to stay within the general perimeters of the code I have, but I would like someone to take a look and see what is going wrong. I am a new programmer, so bear with me.
import turtle
def drawStar(n, l):
"""Get turtle t to draw a star with n sides at l length"""
for i in range(n):
t.forward(l)
t.left(36)
t.forward(l)
t.left(36)
drawStar(5, 100)
wn.exitonclick()
It says that the problem is on line 6 (drawStar(5, 100))
Besides the syntax error discussed, you have a logic error. Consider your t.left(36) statement, or later t.left(144) statement. The angle passed is actually a function of n and making it a constant as you have means this routine only works for one value of n. Consider:
drawStar(7, 100)
You don't get a seven pointed star, just some portion of a (duplicated) five pointed star. Which is not what your docstring claims about n. If we instead do:
import turtle
def drawStar(n, l):
"""Get turtle to draw a star with n sides of l length"""
for _ in range(n):
turtle.forward(l)
turtle.left(2 * 360 / n) # calculate the angle
drawStar(7, 100)
turtle.exitonclick()
We can still get our five pointed star if we want but we can also get a seven pointed star:
Unfortunately, this logic only works for odd values of n. Even values give us back regular polygons of n / 2 sides. We need a different formula to generate stars with an even number of points...
The issue that t is undefined. If t is supposed to invoke some method in from the turtle module directly, use:
import turtle as t

generate mouse velocity when only integer steps are allowed

I write a simple program in python which includes moving my mouse (I do his with PyUserInput).
However: It is only allowed to move the mouse in integer steps (say pixels).
So mouse.move(250.3,300.2) won't work.
I call the move function about 30 times in a second and move the mouse a few pixels. The speed with which I move the mouse varies from 0.5-2.5px/call. Rounding gives me 1-3 (move only want ints) which does not really represent the speed.
I search for a solution (maybe generator?) which takes my current speed (e.g. 0.7px) and gives me back a pattern (like a PWM Signal) out of 0 and 1 (e.g. 1,1,0,1,1,0...) which yields the 0.7px in average.
However this generator has to be adaptive because speed is constantly changing.
I am quite new to python and stuck with the last point: The variability of the generator function.
Here is what I have so far:
# for 0.75px/call
def getPWM(n):
nums = [1,0,1,1]
yield nums[n%4]
What you need to do is keep track of the previous position and the desired current position, and hand out the rounded coordinate. You could track the previous position in a function but it's much easier to do it in a class.
class pwm:
def __init__(self):
self.desired_position = 0.0
self.actual_position = 0
def nextPWM(self, speed):
self.desired_position += speed
movement = round(self.desired_position - self.actual_position)
self.actual_position += movement
return movement

How to Break Infinite Loop in Turtle Graphics Python

I wrote the code for an assignment which completes the task required. Which is to draw the shape of a polygon from user input and draw the amount of shapes per side number specified. The only problem is after the shape is drawn the arrow just keeps tracing through in an infinite loop. I tried using break at the end but it did not work.
from turtle import *
def polygon(n, length):
Screen()
shape('turtle')
mode('logo')
n = input ("Enter number of sides ")
print ("you entered ", n)
length = input("Enter the length of sides ")
print ("you entered ", length)
n=int(n)
length=int(length)
for side in range(n):
forward(length)
right(360/n)
while side in range(n):
right(360/n)
for side in range(n):
forward(length)
right(360/n)
What I have so far will technically work for the assignment, however the infinite loop at the end is annoying me.
The main problem is that the while loop goes for an infinite amount of time.
#This is infinite loop because 'side' iterator is ALWAYS in the sequence returned from range function
while side in range(n):
Also, with the current structure
of your code the function does nothing and only wastes space (you probably call it from the shell which is
understandable). There's a few more redundancies that we can get ride of too. Lets design your script so that the turtle's
polygons can be controlled from the function you created. Hopefully you'll see how powerful the turtle module
can be when utilized with recursion and a proper use of functions.
Lets look at the declarion of your polygon function 1st. The reason I feel your script should revolve around your
polygon function aside from the natural convience of functions is because of the parameters you included in the script.
Although they are not needed (here atleast) per the implied design of your script, the inclusion of them implies A: You
intended for this function to control the turtle, or B: You don't quite understand how functions/parameters work. To
offer more of a learning experience we should definitely focus this script around that function in either case.
def polygon(n,length): #<--- get ride of 'n' & 'length' parameters
def polygon(n=None,length=None): #<---These are defualt values if you wish to go with that direction
def polygon(): #<---This is the declaration I'll follow for aiding your script
Get rid of the paramaters for now. We'll bring them back in a nested function later. Next we're going to add the rest
of the script to the polygon function. Because your n and length variable collect input, it renders the parameters
for the polygon function useless. It's not an either or scenerio, with some control flow you can have both if you
wanted. Before we add the script to our polygon function I'd like to point out how you declared the variables twice, the
second time you converted them to integers. Python allows us to nest them in a int() function the 1st time we declare
them.
n = input("Enter num ")
n = int(n) #<---instead of these 1st 2 lines, do the 3rd line below.
n = int(input("Enter num: ")) #<--1 line of code that is equally as readable as 2.
After modifying both the n & length variables, lets add everything into our polygon function (except the while loop,
get rid of everything involved with that). Notice that the Screen,shape, and mode functions have been moved below the
variable declarions. This is so the turtle window does not jump in front of the user while they're inputing information
into the program.
def polygon():
n = int(input("Enter number of sides: "))
print("You entered %d sides.\n"%(n))
length = int(input("Enter length of sides: "))
print("Your sides are %d pixels long.\n"%(length))
Screen()
shape('turtle')
mode('logo')
Now that we have a clean and readable function lets handle our business with creating polygons. For this we'll use
a nested function that utilizes both recursion and parameters. We'll call it 'looper'. The reason being is that your
assignment is to make an equal amount of polygons that there are sides (in otherwords, num of polygons == n). looper will
achieve that for us. 1st it will take in the variables established in polygon as parameters. Then we'll use your previous
for loop inside.
def looper(n,length,loops=n): #notice the 'loops=n' default parameter, this allows to keep track of it recursively
if (loops > 0): #As long as loops is greater than zero this functin will repeat itself as many times as 'n'
for side in range(n):
forward(length)
right(360/n)
penup()
#penup after the forloop so that the turtle will not draw while searching for next polygon space
setposition(xcor()+length,ycor()+length) #xcor() and ycor() return the current position of the turtle
#notice that we add it to the length of of our sides, this is how the turtle will space out the polys.
#I would even experiment with things like setposition(xcor()+(length*2),ycor()+(length*2))
pendown() #after turtle find the position we we use pendown() to prepare to draw again
loops -= 1 #this decrements the loops parameter so that the functin will not call itself infinitely
#(stack overflow)
looper(n,length,loops) #recursively call our looper function again
return #I personally always return the end of recursive functions to be safe, this may be redundant
Essentially recursion is when a function calls itself within itself repeatedly to perform a task. To make sure that it
eventually ends we tell the program: "Only draw polygons if there are any loops" furthermore after the functions performs
it's duties we tell it "subtract loops by 1" to make sure that the loops will eventually be zero. This and the return
statement (a rough equivalent to what you were referring to as 'break') will assure us that we do not perfom tasks
an infinite amount of times. The last step in this code is to make sure that you actually call the polygon function
so your code will run AND to also call looper(n,length) and the end of your polygon function for the same reason.
Your code should look something like this:
from turtle import *
def polygon():
n = int(input("Enter number of sides: "))
print("You entered %d sides.\n"%(n))
length = int(input("Enter length of sides: "))
print("Your sides are %d pixels long.\n"%(length))
Screen()
shape('turtle')
mode('logo')
def looper(n,length,loops=n):
if (loops > 0):
for side in range(n):
forward(length)
right(360/n)
penup()
setposition(xcor()+length,ycor()+length)
pendown()
loops -= 1
looper(n,length,loops)
return
looper(n,length)
polygon()
I pretty much did the assignment for you, but if you learned a thing or two then my goal is achieved. I hope I helped any!

Understanding recursion in Python 2 (Think Python, exercise 5)

I'm going through Think Python and I've reached recursion which is turning to be a great pain to understand for me.
There's this exercise, number 5, that shows me this piece of code:
def draw(t, length, n):
if n == 0:
return
angle = 50 #sets angle
fd(t, length*n) #make a turtle() "t" go forward length*n pixels while drawing
lt(t, angle) #makes turtle "t" turn left on itself "angle" (50) degrees
draw(t, length, n-1) #1st call
rt(t, 2*angle) #makes turtle "t" turn right "2*angle" (100) degrees
draw(t, length, n-1) #2nd call
lt(t, angle) #makes turtle "t" turn left "angle" (50) degrees
bk(t, length*n) #makes turtle "t" go backwards length*n pixels
And asks me to think of what it does and then run it. I ran it and I had trouble understanding why it does what it does.
It is a much more complex case of recursion that the ones the books presented for explaining this device and I cannot understand it.
Lets make n for example 2 in order to understand a simple instance of this problem:
What I can make out is that the code calls itself until n=0 up to the first call consecutively, then returns the control to n=1 and makes the remaining lines of code from call 1 to call 2. It makes the second call with n=0 and returns but I cannot understand what instance of the function it returns the control of the program.
I'd be glad if someone could point me in the right direction as how to think this kind of recursive code by myself, how can I make use of it (when a for statement wouldn't quite make it) and a way to schematize the way it works (with some sort of diagram, for example?).
I have this:
function called with n=2
function called with n=1
function called with n=0; returns to:
function called with n=1 makes the 2nd call to the function with n=0
function called with n=0; returns to where?
??????
As you can see it is quite impractical for, let's say, a function call with n = 7.
A function always returns directly to its caller. Your recursive function does some work, calls itself, then when the call returns, does some more work, then calls itself another time, then when that returns, does some final work, before the function ends and itself returns:
work
call
work
call
work
return
That is, unless n == 0 is true, then the function immediately returtns. Every recursive call subtracts 1 from n so as long as n was positive to start with, your recursion ends at some point.
Recursion is simply the act of running the same function again, so you can substitute each call in the above 'diagram' with the same jobs being executed. Lets do this once:
n = 2
work
n = 1
work
call
work
call
work
work
n = 1
work
call
work
call
work
return
work
return
I've added in the value for n, provided we start with n = 2. Of course, once you get down to n = 0, the call immediately returns; we can fill that in too:
n = 2
work
n = 1
work
n = 0
return
work
n = 0
return
work
return
work
n = 1
work
n = 0
return
work
n = 0
return
work
return
work
return
Now we have the full call tree for your recursive function, for n = 2. For higher values of n, just keep indenting and filling in the work - call - work - call - work - return lines anywhere there is a call line for the previous level, and you can build a full call tree for any recursive function.
So I've met the same issue to understand this exercice and i think there is nothing better than a schema or a picture to easily understand it , so here is my explanation for the first iteration of the code (using this same logic you'll understand the rest of the code easily) :

Categories

Resources