Lab 10 - Changing Arguments & Recursion
Directions for Labs
- Submit your completed lab file online to CourSys (not Canvas). Labs are marked on completion, not correctness, so complete each part to the best of your ability and learn!
- It is recommended that students attend in-person lab sections for lots of help!
- If you would like to attend an in-person lab section, you are welcome to come to any (or more than one) lab section.
- There is no need to attend the section you are enrolled in.
- There is no need to attend any lab sections: there is no attendance taken.
- You can complete the lab on your own time or own computer if you like.
- While completing these labs, you are encouraged to help your classmates and receive as much help as you like. Assignments, however, are individual work and you must not work with another person on assignments.
Part 1) Changing Arguments
- Inside your
cmpt120
folder, create a new folder forlab10
and make alab10.py
file. - Create a function named
change_number(...)
which accepts one parameter: a number.- The function only needs one line: add 1 to the function's parameter.
- Example:
def change_number(num): num = num + 1
- Add the following code to the main part of your program, but don't run it yet!
num_oranges = 3 change_number(num_oranges) print("Num Oranges: ", num_oranges)
- First predict what the program will print.
- Next, run the program and test it. Think about if it met your expectations.
- Change your main code to set
num_oranges
to be a floating point number.- First predict what the program will print.
- Next, run the program and test it. Think about if it met your expectations.
- Create a function named
change_list(...)
which accepts one parameter (a list).- Make the function add one to the first element of the list, such as:
my_list[0] += 1
- In the main code, create a new list variable of three numbers (such as
ages = [11, 12, 13]
). Pass it to the function then print that list in main. - First predict what the program will print.
- Next, run the program and test it. Think about if it met your expectations.
- Make the function add one to the first element of the list, such as:
- Create a new function named
change_string(...)
which appends ana
to the end of its string parameter.- As before, create a string variable in main, pass it to the function, then have main print its value.
- First predict what the program will print.
- Next, run the program and test it. Think about if it met your expectations.
- Repeat this test for a dictionary. Set the dictionary to have a key "
apple
". Have the function change this key's value, along with adding a new key-value pair.- Call from main as above.
- First predict what the program will print.
- Next, run the program and test it. Think about if it met your expectations.
- In your lab add a comment about which variables in the main code have their values changed by the functions.
- In main, create a list of three integers and then pass the first element to the
change_number(...)
function such as:
change_number(my_list[0])
- Print the list to see its final value in main.
- First predict what the program will print.
- Next, run the program and test it. Think about if it met your expectations.
- Add a comment mentioning the difference between passing a list-of-integers to a function, and passing an element of the list.
- Repeat the test for
change_list(...)
, but this time pass in a copy:- In main, create a new list of three numbers.
- Pass a copy of the list into the function, such as one of the following three ways:
change_list(my_list[:])
or
change_list(my_list.copy())
or
change_list(list(my_list))
- Print the list in main and predict if it will change. Run it!
- Add a comment describing your findings.
- Move all your code from the main section into its own function called
part1_passing_to_functions()
so your code is ready for part 2!
Part 2) Recursive Line
- Add a Turtle to your program:
- Importing the package
- Creating a turtle (I named mine
monet
). - Set the turtle's speed to something slow (1 is good to start).
- Add the
exitonclick()
call at the end as usual.
- Create a new function named
draw_row(n)
:- The function will be recursive.
- For the base case fo
n == 0
, have it write the text "0 - Done row
". -
Hint - write:
You can write text to the screen with:monet.write("0 - Done row")
. - For the recursive step, have it draw a row like the following (for
n==3
):
- Detailed steps (if needed; OK to try without following these):
- Point right:
Put the pen down and set the heading to 0 (point to the right). - Display
n
:
Write to the screen the value ofn
. - Draw a bar:
Move forward 50 and then stamp. - Recursive step:
Recursively calldraw_row()
with argumentn-1
- Move back to where this call started from:
Put the pen up, and the move backward 50.
- Point right:
- From main code, call your function passing in an argument 3.
- Run the program.
- Test your program with other values of
n
between 0 and about 6. - Troubleshooting (as needed):
- There is no loop in this code. It is recursive because it calls itself.
- Ensure your recursive function has a base case (n == 0 in this case) which does not call itself.
- Ensure that other cases call itself but break the problem down a little by passing in
n - 1
. - Debug with:
n=0
:
n=1
:
n=6
:
- Try stepping through your program with the debugger if it's not working.
- The full code is available near the end of this lab if you are absolutely stuck!
Part 3) Draw Tower
- Create a new recursive function named
draw_tower(...)
- Pass in argument
rows
to represent how many rows the tower should have. - If
rows=3
then draw three rows using the abovedraw_row(n)
function. Bottom row would be length 3, then next row up is length 2, then length 1. - Move up and down:
- Move up 50 for each row.
- When done the row, move back down 50 so that when done drawing the tower the turtle is back to the start.
- At the very top, print "Done Tower".
- Your tower should look like:
- Try implementing this function on your own if you can! Here are some hints to walk you through it.
-
Hint - Recursion:
Recursion will be on the argumentrows
. Base case isrows == 0
, each recursive call executesdraw_tower(rows - 1)
. -
Hint - Base Case:
For the base case (rows == 0
), move up 50, write the "Done Tower" text, and then move back down 50. -
Hint - Recursive Step:
For the recursive step (rows != 0
) move up, calldraw_row(rows)
, then make the recursive calldraw_tower(rows - 1)
. Finally, move back down to reset the turtle to where it was when the function started. -
Hint - Move Up/Down:
To move up, set the turtle's heading to up (monet.setheading(90)
) and move forward 50. Ensure the pen is up or down as needed. To move down, set heading to 90 and move backward 50.
- Pass in argument
- Call it from your main program:
draw_tower(6)
. - Troubleshooting Ideas:
- Set the turtle speed to 1, and then watch it run. See where it goes wrong.
- Call
draw_tower(0)
and prove it draws the text OK:
- Call
draw_tower(1)
and see if its behaviour meets expectations:
- The full code is available near the end of this lab if you are absolutely stuck!
Part 4) Optional Challenges
- [Optional] Try using recursion to draw
n
boxes all with their lower left corner at (0,0), each one bigger than the next one.- Idea: Plan out your base case and recursive step first.
- [Optional] Try using recursion to draw
n
boxes all centered at (0,0), each one bigger than the next one.- Idea: Plan out your base case and recursive step first.
- [Optional] Try using recursion to a series of
n
triangles, each with their lower left at (0,0).- Idea: Plan out your base case and recursive step first.
- [Optional] Create an algorithm that makes it look like the view is looking straight down a long train tunnel.
- Idea: The boxes of the tunnel that are nearest the viewer will be further apart compared to ones in the very distance.
- Idea: The boxes of the tunnel that are nearest the viewer will be further apart compared to ones in the very distance.
Full Code
If you need it, here is the full recursive code.
Please only use after you have really tried to write the code yourself with the above hints!
-
Hint - Full code for row
def draw_row(n): if n == 0: monet.write("0 - Done row") else: monet.pendown() monet.setheading(0) monet.write(str(n)) monet.forward(50) monet.stamp() draw_row(n - 1) monet.penup() monet.backward(50)
-
Hint - Full code for tower
def draw_tower(rows): monet.penup() if rows == 0: monet.setheading(90) monet.forward(50) monet.write("Done Tower") monet.backward(50) else: monet.setheading(90) monet.forward(50) draw_row(rows) draw_tower(rows - 1) monet.setheading(90) monet.backward(50)
Submission
Uncomment all your code before submitting.
Submit your lab10.py
file to CourSys by Sunday midnight. Remember you can submit up to 3 days late with no penalty if needed (but please plan to get it done on time to stay up to date on the course!)
Topics Covered
- Experiment with changing an argument's value in a function.
- Identify when the value in the calling code changes.
- Identify when the value in the calling code does not change.
- Experiment with recursion graphically.