@extends('template')
@section('title')
Lab 12: Fruitful recursion
@stop
@section('content')
# Lab 12, Part 2: Branching recursion
These problems demonstrate some more complex recursive patterns, because
they involve more than one recursive call. **Open the `branching.py` file in
the starter folder** to work on this part of the lab.
## Branching function call frames
Partner A
Partner B
Before you try to solve branching recursive problems, you need to be able
to understand how the function call frames work. Here's an example of a
fruitful recursive function that uses branching recursion:
```py
def findMax(numbers):
"""
Returns the largest number from a list of numbers. Returns None if
the list is empty.
"""
if len(numbers) == 0: # No numbers -> result is None
return None
elif len(numbers) == 1: # One number -> that's the max
return numbers[0]
else:
# Figure out where the middle of the list is
midpoint = len(numbers) // 2
# Get the max of the first half and the max of the last half
maxFirst = findMax(numbers[:midpoint])
maxLast = findMax(numbers[midpoint:])
# If either max is None, we can't compare them; return the other one
if maxFirst == None:
return maxLast
elif maxLast == None:
return maxFirst
# If the first max is bigger: return it, otherwise return the second
elif maxFirst > maxLast:
return maxFirst
else:
return maxLast
```
Look at the function definition above, and draw the function call frames
for a call to `findMax([3, 1, 2])` to answer the questions below (click
on each question to show the answer, but only after you've come up with a
guess).
1. How many function call frames are created when evaluating
`findMax([3, 1, 2])`, and what is the argument for each frame?
There are a total of 5 function call frames, with the following arguments:
1. `[3, 1, 2]` (the original function call frame)
2. `[3]` (the first half of the original list)
3. `[1, 2]` (the second half of the original list)
4. `[1]` (the first half of smaller list)
5. `[2]` (the second half of smaller list)
2. How many of those are base-cases, and how many are recursive?
Three of them are base cases (the ones with length-1 lists) and two are
recursive (the original frame and the `[1, 2]` frame).
3. What is the result for `findMax([3, 1, 2])`?
3, which is the largest number in the list.
## `printCoinPossibilities`
Partner B
Now that you've seen an example of branching recursion, try to use it to
solve this (non-fruitful) problem: The `printCoinPossibilities` function
should print all possible results of flipping a certain number of coins,
given the results of some of the flips, plus the final number of flips.
Each result it prints will be a string consisting of the letters 'h' for
heads and 't' for tails. So for example, the string `'hht'` represents
flipping heads twice followed by tails once.
Note that the function takes two arguments: a string listing results
observed so far, and an integer specifying the total number of flips to
make. The function should print all possible sequences of flips that
contain the specified total number of flips, where the first few flips
are as specified in the observed results. So for example, if the observed
results are 'ht' and the total number of flips is 3, the possibilities
are 'hth' and 'htt'. If the number of observed results is greater than or
equal to the required number of flips, the function should just print the
observed flips, even if there are more than required. So
`printCoinPossibilities('hht', 2)` would just print 'hht'. Here are more
examples:
```py
printCoinPossibilities('hht', 2) # prints 'hht'
printCoinPossibilities('hh', 3) # prints 'hhh' and 'hht'
printCoinPossibilities('', 2) # prints 'hh', 'ht', 'th', and then 'tt'
printCoinPossibilities('', 3)
# prints all 8 possibilities starting with 'hhh' and ending with 'ttt':
# hhh
# hht
# hth
# htt
# thh
# tht
# tth
# ttt
```
Note: You can use the provided `test_branching.py` file to test this
function.
Hints:
1. The base case is not just when the number of flips is 0.
2. Only the base case needs to print anything.
3. The second argument does not decrease in the recursive calls. Instead,
the first argument gets longer.
@include('/labs/lab12/_toc')
@stop