In: Computer Science
def seq3np1(n):
""" Print the 3n+1 sequence from n, terminating when it reaches 1. args: n (int) starting value for 3n+1 sequence return: None """
while(n != 1):
print(n)
if(n % 2) == 0: # n is even
n = n // 2 else: # n is odd
n = n * 3 + 1
print(n) # the last print is 1
def main():
seq3np1(3)
main()
Using the provided code, alter the function as follows:
First, delete the print statements in the function
Now we will need a local variable to keep track of the count.
It would make sense to call it count.
It will need to be initialized to 0 before we begin the loop.
Once inside the loop, we will need to update count by 1 (increment), so that we can keep track of the number of iterations.
When the loop terminates (we get to 1), return the value of count.
This demonstrates an important pattern of computation called a counter (note that it is a type of accumulator). The variable count is initialized to 0 and then incremented each time the loop body is executed. When the loop exits, count contains the result — the total number of times the loop body was executed.
Since the function now returns a value, we will need to call the function inside of a print statement or save the result in a variable for later printing in order to see the result.
Now that we have a function that can return the number of iterations required to get to 1, we can use it to check a wide range of starting values. In fact, instead of just doing one value at a time, we can call the function iteratively in our main, each time passing in a new value. The algorithm for your main is as follows:
Ask the user for a value to use for the upper bound of your range
You must verify that the value is positive, since your function will not work on negative values. If the value is not positive, you should END the program.
Create a for loop using an iteration variable called start that provides values from 1 up to (and including) the user supplied upper bound.
Call the seq3np1 function once for each value of start.
Write a print statement that prints the value of start and the number of iterations.
Part B
Next we will write a new function (not in the main) that will take an upper bound value and use the turtle graphics library to a line graph the number of iterations, where the x axis is the upper bound and the y axis is the number of iterations. This provides an interesting visual that allows you to see the relative number of iterations for each value. You will need to:
Use a variable to keep track of the maximum number of iterations
Use the turtle library’s Screen command setworldcoordinates
You can use the command to resize the window and make your graph re-scale according to the values you are graphing.
Use a turtle to write out the largest number of iterations required to get to 1 in the sequence so far.
Scanning this list of results causes us to ask the following question: What is the longest sequence? The easiest way to compute this is to keep track of the largest count seen so far. Each time we generate a new count, we check to see if it is larger than what we think is the largest. If it is greater, we update our largest so far and go on to the next count. At the end of the process, the largest seen so far is the largest number of iterations we used to generate a sequence.
We can also use this value to update the y axis of the world coordinate. You can initialize your world coordinates to (0, 0, 10, 10), but then update them each time you get a new x value and new y value that is greater than the current max. You will need to update the graph using setworldcoordinates on every iteration (review the documentation before proceeding):
positive x axis should be the current value of the loop iterator + 10
we are just adding +10 to give a little room so we can see our results more easily
The positive y axis should be the max_so_far value + 10
The negative x and y values should both be 0
In other words, the world coordinates should grow with your graph. Below is the basic algorithm:
The number of iterations (the upper limit) should be a parameter to your function
Create a turtle and a window.
Create an additional turtle object to write out the maximum data
You will have two turtle objects, each completing their own task
Set the world coordinates to (0,0,10,10)
Create a variable call max_so_far and initialize it to zero
place this initialization outside the for loop so that it only happens once
Write a for loop using the number of iterations (the upper limit) that was passed as a parameter
Now, inside the for loop, save the result of the seq3np1 function in a variable called result
Then we can check result to see if it is greater than max_so_far
If so, update max_so_far with the new, greater value
Using your writer turtle, clear the previous text if necessary
Add a label, “Maximum so far: <iteration>, <result>” using the turtles write() command to write the iteration and result in the upper left corner of the screen (you can just use the max_so_far value as the y coordinate for your label)
Set the world coordinates of the screen to the current iteration + 10 and the max_so_far + 10 values.
Make sure you review the turtle’s write() command. It doesn’t work the same as print. You will have to create a single string before writing.
Graph the result with your turtle. Hint: you are graphing on an x,y coordinate plane. You are trying to make a graph of the max number of iterations that the seqn3p1() function runs for. What do you think would make good x and y values for a graph of this data?
Working code implemented in Python and appropriate comments provided for better understanding.
Source Code for main.py:
import turtle
def seq3np1(n):
""" Print the 3n+1 sequence from n, terminating when it reaches
1.
args: n [int] - starting value for 3n+1 sequence
return: count [int] - the number of iterations the loop executed
until n = 1.
"""
count = 0
while(n != 1):
if(n % 2) == 0: # n is even
n = n // 2
else: # n is odd
n = n * 3 + 1
count += 1
return count
def drawGraph(iteration):
""" Draws a graph with a positive integer on the x-axis, and the
number of iterations it takes for the 3n+1 sequence to bring that
integer to 1 on the y-axis. The graph actively marks where the
current maximum value is.
args: iteration [int] - the upper bound of the function as inputed by the user in Part A
return: none.
"""
grapher = turtle.Turtle()
grapher.speed(0)
grapher.up()
grapher.goto(0,0)
grapher.down()
writer = turtle.Turtle()
writer.speed(0)
wn = turtle.Screen()
wn.setworldcoordinates(0, 0, 10, 10)
max_so_far = 0
for i in range(1, iteration + 1):
result = seq3np1(i)
print("The number " + str(i) + " has " + str(result) + "
iterations.")
if result > max_so_far:
max_so_far = result
writer.clear()
writer.up()
writer.goto(i, max_so_far)
# I intentionally place the turtle at the point of the max because
I personally think it looks better there instead of the top left
corner. (pls don't take points off.)
writer.write("Maximum so far: " + str(max_so_far))
wn.setworldcoordinates(0, 0, i + 10, max_so_far + 10)
grapher.goto(i, result)
wn.exitonclick()
def main():
##### PART A #####
upper = int(input("Please enter an upper bound for the function:
"))
start = 1
while (start < upper):
start += 1
count = seq3np1(start)
print("The number " + str(start) + " has " + str(count) + "
iterations.")
##### PART B #####
drawGraph(upper)
main()
Code Screenshots:
Sample Output Screenshots: