This function prints the given `text`

the given `numberOfTimes`

.

```
def repeatPrint(text, numberOfTimes):
# Write solution here...
```

For example:

```
repeatPrint('Hello!', 3)
```

Should output:

```
Hello!
Hello!
Hello!
```

In [31]:

```
# Implementation of repeatPrint using a for loop:
def repeatPrint(text, numberOfTimes):
for i in range(numberOfTimes):
print(text)
# Let's try it:
repeatPrint('Hello!', 3)
```

In [32]:

```
# Implementation of repeatPrint using a while loop:
def repeatPrint(text, numberOfTimes):
i = 0
while i < numberOfTimes:
print(text)
i += 1
# Let's try it:
repeatPrint('Hello!', 3)
```

Let us now define `repeatPrint`

using a technique called **Recursion**. A *recursive function* is a function that calls itself.

In [33]:

```
# Implementation of repeatPrint using recursion:
def repeatPrint(text, numberOfTimes):
if numberOfTimes == 0:
# If the number of times to print is 0, there is no work to do.
return
# Print the text once.
print(text)
# Now we have one fewer number of times to print the text.
numberOfTimesRemaining = numberOfTimes - 1
repeatPrint(text, numberOfTimesRemaining)
# Let's try it:
repeatPrint('Hello!', 3)
```

Every recursive function has two important parts: the **base case** and the **recursive case**.

The **base case** occurs when we have the simplest possible input to the function, where the answer is obvious. For `repeatPrint`

the base case occurs when `numberOfTimes == 0`

.

The **recursive case** occurs all other times from the **base case** where we are required to call the function itself with a different input (that gets one step closer to the base case). For `repeatPrint`

the recursive case occurs when `numberOfTimes > 0`

.

In [ ]:

```
# What happens if we forget the base case?
def repeatPrint(text, numberOfTimes):
# Print the text once.
print(text)
# Now we have one fewer number of times to print the text.
numberOfTimesRemaining = numberOfTimes - 1
repeatPrint(text, numberOfTimesRemaining)
# Let's try it:
repeatPrint('Hello!', 3)
# Answer: repeatPrint will recursively call itself repeatedly, without stopping!
# So this bad code. Similar to an infinite loop.
```

Let us try out recursion with another example.

The following sequence is called the **Fibonacci sequence**:

`0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...`

Can you see the pattern in this sequence?

The **Fibonacci sequnce** is defined as follows:

```
F(0) = 0
F(1) = 1
F(n) = F(n - 1) + F(n - 2), for n >= 2
```

We can expand this out a bit to see the first few elements of this sequence:

```
F(0) = 0, by definition
F(1) = 1, by definition
F(2) = F(1) + F(0) = 1 + 0 = 1
F(3) = F(2) + F(1) = 1 + 1 = 2
F(4) = F(3) + F(2) = 2 + 1 = 3
F(5) = F(4) + F(3) = 3 + 2 = 5
...
```

This sequence appears in algorithms, math, and in nature in various places. We will not discuss the sequence itself in detail, but you can read more about it here: https://en.wikipedia.org/wiki/Fibonacci_number.

Let us define a function `fib(n)`

that computes the $n^{th}$ Fibonacci number.

```
def fib(n):
# Write solution here...
```

In [34]:

```
# Implementation of fib using for loop:
def fib(n):
if n == 0 or n == 1:
return n
fib_i_prev_prev = 0 # Initialized to F(0)
fib_i_prev = 1 # Initialized to F(1)
for i in range(n - 1):
# Compute the next number in the sequence
fib_i = fib_i_prev_prev + fib_i_prev
# Save state to use for the next computation
fib_i_prev_prev = fib_i_prev
fib_i_prev = fib_i
return fib_i
# Let's try it:
fib(4)
```

Out[34]:

In [35]:

```
# Implementation of fib using recursion:
def fib(n):
# Base case:
if n == 0 or n == 1:
return n
# Recursive case:
return fib(n - 1) + fib(n - 2)
# Let's try it:
fib(4)
```

Out[35]:

Let us practice how to understand recursive functions with a couple more examples.

In [36]:

```
# What is the behavior of this function?
def mystery(a):
if a == 0:
return 0
return a + mystery(a - 1)
mystery(4)
# Answer:
# mystery(a) = 0 + 1 + 2 + ... + a
```

Out[36]:

In [37]:

```
# What is the behavior of this functioin?
def mystery2(a, b):
if b == 0:
return 0
return a + mystery2(a, b - 1)
mystery2(5, 4)
# Answer:
# mystery2(a, b) = a * b
```

Out[37]: