@extends('template') @section('title') Lab 12: Fruitful recursion w/ Turtle @stop @section('content') # Lab 12, Part 2: Fruitful recursion w/ Turtle For this part of lab, open the file `fruitfulTurtles.py`. This is where you will add your code. ## Task 0. Consider a different approach for rows of boxes We designed recursive Turtle functions that would draw a pattern a given number of times. For example, when we invoked `row(3, 50)` it would draw **3** squares. row(3, 50) To make things more challenging, let's change it up a bit. We will tell the function the starting side length of the first square, and a shrink factor and a minimum side length that must be met in order for a square to be drawn. Consider the function `newRow` below: ```py def newRow(size, shrinkFactor, minimumSize): if size < minimumSize: pass else: square(size) fd(size) newRow(size*shrinkFactor, shrinkFactor, minimumSize) bk(size) ``` Here are two sample invocations of `newRow`: ```py newRow(size, shrinkFactor, minimumSize) ``` ### Example invocation 1: ```py newRow(50, 0.5, 20) ``` produces newRow(50, 0.5,  20) The first box has size 50, the second 25, and the third would be 12.5, but 12.5 < 20, so it stops. ### Example invocation 2: ```py newRow(50, 0.8, 20) ``` produces newRow(50, 0.8,  20) The box sides are 50, 40, 32, 25.6, and 20.48. The next one would be 16.38, but that is < 20, so it is not drawn. ## Task 1. Write fruitfulRow Using `newRow` (code above) as your starting point, write `fruitfulRow` so that the fruitful function returns the number of boxes that are drawn. Remember that with fruitful recursion, a value **always** should be returned. How to count the number of boxes drawn? + How many boxes are drawn in the base case? That's the value to return in the base case. + How many boxes are drawn in the recursive case? Use **wishful thinking** and pretend that your recursive case works correctly and returns the number of boxes drawn in your recursive call. ### Example invocations of `fruitfulRow`: ```py In []: fruitfulRow(50, 0.5, 20) Out[]: 2 In []: fruitfulRow(50, 0.8, 20) Out[]: 5 In []: fruitfulRow(100, 0.75, 18) Out[]: 6 In []: fruitfulRow(100, 0.9, 10) Out[]: 22 ``` ## Task 2. fruitfulRowTuple In this next task, we want to create an improved version of the row function that instead of just returning a single value (`squareCount`) it **returns a tuple** indicating how many squares were drawn *and* the total distance travelled by the Turtle.
__Capturing tuples returned from a function__ In order to complete this task, study the following example that demonstrates a function that returns a tuple. ```py def pad(x, y, padding): return x + padding, y + padding ``` Given the above code, make predictions of what the following print statements would produce: ```py x, y = pad(300, 200, 10) print(x) # ??? print(y) # ??? ``` Run your code in Canopy to check your predictions. Note how the function `pad` returns a tuple. Because of this, we can capture its results in a tuple: `x, y = pad(300, 200, 10)`.
Once you understand the above code, copy and complete the following `fruitfulRowTuple` function in your `lab12/fruitfulTurtles.py` file: ```py def fruitfulRowTuple(size, shrinkFactor, minimumSize): if size < minimumSize: return ??? else: square(size) fd(size) ??? = fruitfulRowTuple(size*shrinkFactor, shrinkFactor, minimumSize) bk(size) return ??? ``` __Important observation about the above function:__ Note how the base case also need to return a tuple, `0,0`. It's essential that the value type returned by the base case is consistent with what is returned in the recursive case. Come up with some test cases for your `fruitfulRowTuple`. Try using a shrink factor of 0.5 for easier initial tests and calculations. ## Task 3. nestedSquares Using the skills applied in `fruitfulRow` and `fruitfulRowTuple`, write a fruitful recursive function called `nestedSquares` that draws nested squares as shown in the examples below and returns a tuple with the number of squares drawn and the total length of all squares. Parameters: 1. The **size** (length) of the square to be drawn 2. The **shrink factor** of the successive squares to be drawn 3. The **minimum sidelength** of a square; boxes will only draw a square if the side is greater than this minimum sidelength 4. The **color** of the Turtle's pen
Before writing any code, skim through the following examples and read the **hints** that follow. #### Example A. ```py nestedSquares(400, 0.2, 100, 'blue') ``` 1 square, 1600 length (`400 * 4 sides = 1600`) No more squares drawn because `400 * 0.2 = 80`, and 80 is less than the min sidelength of 100. #### Example B. `nestedSquares(400, 0.4, 100, 'magenta')` 2 squares, 2240 total length ```xml 1600 largest square (400 * 4 sides) + 640 small square (160 * 4 sides) ===== 2240 total length ``` #### Example C. `nestedSquares(400, 0.75, 100, 'black')` 5 squares, 4881.25 total length ```xml 1600 (400 * 4 sides) + 1200 (300 * 4 sides) + 900 (225 * 4 sides) + 675 (168.75 * 4 sides) + 506.25 (126.5625 * 4 sides) ========= 4881.25 total length ``` #### Example D. `nestedSquares(100, 0.8, 20, 'red')` 8 squares, 1664.45568 total length ```xml 400 (100 * 4 sides) + 320 (80 * 4 sides) + 256 (64 * 4 sides) + 204.8 (51.2 * 4 sides) + 163.84 (40.96 * 4 sides) + 131.072 (32.768 * 4 sides) + 104.8576 (26.2144 * 4 sides) + 83.88608 (20.97152 * 4 sides) =========== 1,664.45568 total length ``` ### Hints 1. First, write the recursive function to produce the picture of nested squares. Relevant things to think about: - When does the recursion end? Which parameter(s) determine if it is the base case? - Handle the recursive case: draw one square and let recursion draw the remaining squares. - Adjust the relevant parameters in the recursive call to ensure that the problem gets smaller each time. 2. After the above works, *then* add in the fruitful **counting of squares** only. You will need a variable to keep track of the square count, and you will need to return that value. 3. After the counting of squares works, *then* add the fruitful **sum of all the lengths** drawn. Each time the Turtle moves forward, keep track of that “mileage”. There are hints in [Helpful Hints and Diagrams](/labs/lab12/hints) (see Table of Contents below), in particular, this [Turtle Hints diagram](/content/labs/lab12/hints/turtle-squares-design-patterns.png) may be helpful. ### Argh! My function doesn't work! Help! Try some of these debugging tips:
Draw out the first few cases on paper, and make sure that you have broken down the problem correctly. Additionally, add print statements at the start and end of your function to display each parameter value, e.g. ```py print("nestedSquares(" + str(size) + str(shrink) + ... + ")") ``` This also helps you trace the recursion as it unfurls.
@include('/labs/lab12/_toc') @stop