How to Break Infinite Loop in Turtle Graphics Python - 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!

Related

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

Turtle Graphics with Recursion

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".)

Pancake Flipping: Recursive Python

I'm having a terrible time coming up with an algorithm to flip a "stack" of pancakes,which are really a list of numbers. You're allowed to flip the top at a certain index and above. Even something in pseudo code would be a rolling start, if you don't want to do full Python. i just have trouble with recursion. Not sure if base case should be pancakes.is_in_order() == True or something more like len(pancakes) == 1: return pancakes.
Input example: pancakes = [2,3,1,4] (Top here would be 2. You can flip pancakes[:index] by doing a reverse() on that slice of list)
Need to flip such that you have [1,2,3,4]
Output: # of flips it takes (don't need to show flips, order, etc. Just number of flips. If it's over a dozen, then timing out is fine)

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) :

Need help fixing/refining a while loop sum calculator in python [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Keep in mind that I am still very new to python coding as I am only just into chapter 5 of my python coding class. Keeping that in mind, I am attempting to create a sum calculator using a "while loop" to continue until the user enters a negative number instead of a positive number.
In case I am not entirely clear in my description of my question I will post the exact homework problem here:
Chapter 5, page 200, #8
Sum of Numbers
Write a program with a while loop that asks the user to enter a series of positive numbers. The user should enter a negative number to signal the end of the series. After all the positive numbers have been entered, the program should display their sum.
Now for the code that I have written so far:
def main():
number = float(input('Please enter in a positive number: '))
while number > 0:
positiveNumber()
while number < 0:
calculateTotal()
printTotal()
def positiveNumber():
number = float(input('If you are finished please enter a negative number.' + \ 'Otherwise, enter another positive number: '))
while number > 0:
positiveNumber()
while number < 0:
calculateTotal()
printTotal()
def calculateTotal():
total = 0 + number
def printTotal():
print('The sum of your numbers is: ', total)
main()
In line 11, I have the "+ \" sign there because I wanted to make an enter space there in order to have a cleaner looking text, but that does not seem to work.
I apologize if this question seems "nooby" but I need help making a cleaner/working sum calculator. I would greatly appreciate it if someone can take a look at this code and hopefully help me improve it. Thank you!
Final Edit:
Thank you all for the informative answers! I learned alot (for a "newbie" =]). I used Talon876's answer for my calculator. Thanks again everyone!
If you want a single string to be printed on multiple lines, put a \n in the string.
For example,
print "This is on the first line\nThis is on the second line"
would output
This is on the first line
This is on the second line
It looks like you're mixing a while loop with recursion (calling a method from within itself). I would suggest using a single while loop and an input variable to check for the breaking condition (the input is < 0)
It would look something like this:
sum = 0
number = float(input('Please enter in a positive number: '))
while number > 0:
sum = sum + number
number = float(input('If you are finished please enter a negative number.' + \ 'Otherwise, enter another positive number: ')) #fix this line using the information from the first part of the answer
This will loop until the user inputs a negative number, or 0. If you want to accept 0 as a positive number, change the while condition to number > -1
You can't update a global variable in a python function without explicitly declaring it as a global. Observe:
a = 1
def foo():
a = a + 6 #creates a new variable (a) that is confined to the "foo" namespace.
#Note that it still uses a from the global namespace on the Right hand side
#This is because python looks for a in the "foo" namespace first. When
#it isn't found there, it looks in the global namespace. However, python
#WON'T ASSIGN to something in the global namespace without being told
#to explicitly
print (a)
foo() # 7
print (a) # 1
def foo():
global a #Tell python that it is OK to assign to variable "a" in the global namespace.
a = a + 6
print (a)
foo() # 7
print (a) # 7
However, with this great power comes great responsibility. Many people will tell you to never use global variables. In a lot of ways, they're correct because just about anything you can accomplish with global variables can be accomplished more cleanly using some other method. My hope in writing this is not to convince you to use globals, but to help you understand one of the errors in your code.
One thing that you may want to try is to have your function accept the input number as an argument along with the total to this point and then return the new total.
Good luck!
the problem is 1.you have not declared the variables you are using in function as global,to note the changes being made to them
2.you dont need while loops if you are implementing it by calling a function recursively!you need checking condition lik "if & else"
here is an easy implementation of problem with while loop:
def main():
total=0
number = float(input('Please enter in a positive number: '))
while(number>0):
total=total+number
number = float(input('Please enter in a positive number to continue or a negative no. to stop: '))
print('The sum of your numbers is: %d'% total)
main()
I think you're looking for something like this? But I don't know what style constraints you are required to use.
number = float(input('Please enter in a positive number: '))
to_sum = []
while number > 0:
to_sum.append(number)
number = float(input('If you are finished please enter a negative number.\n' +
'Otherwise, enter another positive number: '))
print('The sume of your numbers is: ', sum(to_sum))
Please note that because the statement you are trying to break onto multiple lines is already within ()'s, you don't need the . You can just break the line.
Did the assignment require you to use so many crazy functions? Also, which version of Python are you using?
One thing you need to learn is how to break up a program into functions. Some problems are better handled by a single block of code than by being split up, and I think this is one of them.
You need to calculate a single sum. You can handle that with a single variable, to which you add more numbers as the user enters them. Your code should be designed around this variable. If you try to split the code up into functions, you either need to use a global variable (not recommended!), or you need to pass the variable around among the functions, or perhaps you could put the variable into an object and then make the functions be "method" functions on the object. But simplest is just to write some code that uses the variable, and make all that code be a single block of code (either one function, or even just the code in your Python program).
Here is a solution:
sum = 0.0 # initial value; we will add values to this
print('Welcome to this program')
while True:
s = input('User: enter data value or a negative number to stop')
x = float(s)
if x < 0:
break
sum += x # add this value to update the sum
print('Here is your sum: {}'.format(sum))
So, here is what is good about the above code. All the places that need to work with the variable sum are all close together, and we can see them. We don't need to declare sum global, because we don't have multiple functions trying to all use it.
Look at that code, and ask yourself: would it be simpler or cleaner if we carved it up into multiple functions? If not, then don't do it.
The only tricky thing here is that we used while True: for the loop. This is because we want to do something (get input), then based on the result, decide whether to break out of the loop or continue, and then finally do something else based on the decision (update the sum).
It's possible to rewrite this to use a "flag" variable, and make the loop while flag: but I don't think it is cleaner:
sum = 0.0 # initial value; we will add values to this
print('Welcome to this program')
continue_loop = True
while continue_loop:
s = input('User: enter data value or a negative number to stop')
x = float(s)
if x < 0:
continue_loop = False
else:
sum += x # add this value to update the sum
print('Here is your sum: {}'.format(sum))
Do you think it is clearer to have the continue_loop flag variable? Some textbooks say you should write your code this way, because they think it is a sin to use break to exit a loop in the middle; they think loops should only exit from the usual place (which, for a while loop, is the top).
What if you really wanted to use functions? Well, you could, but you still shouldn't use a global variable. In fact, if you are writing a "functional" solution, you don't need a sum variable at all!
Here is a functional solution.
def ask_and_sum():
s = input('Hey dude enter a value or a negative to stop')
x = float(s)
if x < 0:
return 0
else:
return x + ask_and_sum()
print('Welcome to this program')
print('Your sum is: {}'.format(ask_and_sum()))
Instead of an explicit loop, this uses "tail recursion", where a function ends with another call to itself. In this case, I personally prefer the explicit loop. What do you think?
P.S. This problem is so simple that it was hard to discuss it without giving you the full answer. I apologize for that. But even if you just copy the code, please look at it, and think about it, and make sure you understand it.

Categories

Resources