# Recursion (2)¶

In this lecture, we will continue with more examples of recursion.

## Recursive Trees¶

```from turtle import *

def tree(trunkLen, angle, shrinkFactor, minLength):
'''Draw tree and return number of branches drawn including trunk'''
if (trunkLen < minLength): # Base case
return 0
else:
# Draw trunk
fd(trunkLen)

# Right branch
rt(angle)
rightBranch = tree(trunkLen*shrinkFactor, angle, shrinkFactor, minLength)

# Left branch
lt(angle*2)
leftBranch = tree(trunkLen*shrinkFactor, angle, shrinkFactor, minLength)

# Maintain invariance
rt(angle); bk(trunkLen)

return 1 + rightBranch + leftBranch

if __name__ == '__main__':
reset()
speed(0)
lt(90) # Face north first to grow the tree upwards
print("Num branches:", tree(100, 45, 0.5, 12))
done()
```
```Num branches: 15
```

## Recursion vs. Iteration: `sumList`¶

Let us consider a simple example of an iterative vs recursive approach to the same problem.

```def sumListIterative(numList):
"""Returns sum of given list numList"""
sum = 0
for num in numList:
sum += num
return sum
```
```sumListIterative([3, 4, 20, 12, 2, 20])
```
```61
```
```def sumList(numList):
"""Returns sum of given list numList"""
if numList == []:
return 0
else:
return numList + sumList(numList[1:])
```
```sumList([3, 4, 20, 12, 2, 20])
```
```61
```

## Finding Files On Our Computer¶

This task will help us understand some of the key differences and advantages that recursion might offer over writing iterative programs. Ultimately, we’re aiming to write an iterative and recursive version of a program that takes in a nested list of lists (the nesting could go on arbitrarily) corresponding to files and folders within folders on a computer and returns whether a file we’re looking for is in the nested list or not.

But first we’ll write a simpler version of the program to get started.

## Finding Files In A List¶

Let’s first write an iterative and recursive function for finding a file from a single list of file names.

```def fileFoundIterative(files, target):
"""
Iterative function that returns True if the list of files
contains the target file and False otherwise.
"""

for file in files:
if file == target:
return True
return False
```
```files = ["homework", "puppy", "films"]
print(fileFoundIterative(files, "puppy"))
print(fileFoundIterative(files, "kitten"))
```
```True
False
```
```def fileFound(files, target):
"""
Recursive function that returns True if the list of files
contains the target file and False otherwise.
"""

if files == []:
return False
else:
return files == target or fileFound(files[1:], target)

files = ["homework", "puppy", "films"]
print(fileFound(files, "puppy"))
print(fileFound(files, "kitten"))
```
```True
False
```

## Finding Files From Nested Lists¶

We now look at the general task of finding files when we have folders within folders and compare the iterative and recursive approaches.

```def fileFoundIterative(folder, target):
"""
Iterative function that returns True if the folder
(nested list) contains the target file and False otherwise.
"""

# create an initial list or pile of files/folders to look through
pile = [item for item in folder]

# keep looking while the pile isn't empty
while len(pile) > 0:

# get and remove the last item from the pile
# we can use the pop() list method for this
item = pile.pop()

# if the item is a folder (list) add each item
# inside the folder onto the pile
if type(item) == list:
for obj in item:
pile.append(obj)

# otherwise check if the current file is our target
elif item == target:
return True

return False

nestedFolders = ["homework", ["cat", "puppy", "goat"], ["films", "books"]]
print(fileFoundIterative(nestedFolders, "puppy"))
print(fileFoundIterative(nestedFolders, "poems"))
```
```True
False
```
```def fileFound(folder, target):
"""
Recursive function that returns True if the folder
(nested list) contains the target file and False otherwise.
"""
# base case
if folder == []:
return False
else:
firstItem = folder

# check if the first item is itself a folder (list), if so, recurse
if type(firstItem) == list and firstItem != []:
return fileFound(firstItem, target)

# otherwise we know the item is a file name, so we check if this
# is our target, or if the remaining files/folders contain our target
return firstItem == target or fileFound(folder[1:], target)
```
```nestedFolders = ["homework", ["cat", "puppy", "goat"], ["films", "books"]]
print(fileFound(nestedFolders, "puppy"))
print(fileFound(nestedFolders, "poems"))
```
```True
False
```