Skip to content

Commit d0ce28b

Browse files
committed
Add fibonacci template and unit tests for recursion and memoization
1 parent ae9e87a commit d0ce28b

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

Diff for: source/recursion.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!python
2+
3+
def fibonacci(n):
4+
"""fibonacci(n) returns the n-th number in the Fibonacci sequence,
5+
which is defined with the recurrence relation:
6+
fibonacci(0) = 0
7+
fibonacci(1) = 1
8+
fibonacci(n) = fibonacci(n - 1) + fibonacci(n - 2), for n > 1"""
9+
# Check if n is negative or not an integer (invalid input)
10+
if n < 0 or not isinstance(n, int):
11+
raise ValueError('fibonacci is undefined for n = {!r}'.format(n))
12+
# Implement fibonacci_recursive, _memoized, and _dynamic below, then
13+
# change this to call your implementation to verify it passes all tests
14+
return fibonacci_recursive(n)
15+
# return fibonacci_memoized(n)
16+
# return fibonacci_dynamic(n)
17+
18+
19+
def fibonacci_recursive(n):
20+
# Check if n is one of the base cases
21+
if n == 0 or n == 1:
22+
return n
23+
# Check if n is larger than the base cases
24+
elif n > 1:
25+
# Call function recursively and add the results together
26+
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)
27+
28+
29+
def fibonacci_memoized(n):
30+
# TODO: Memoize the fibonacci function's recursive implementation here
31+
pass
32+
# Once implemented, change fibonacci (above) to call fibonacci_memoized
33+
# to verify that your memoized implementation passes all test cases
34+
35+
36+
def fibonacci_dynamic(n):
37+
# TODO: Implement the fibonacci function with dynamic programming here
38+
pass
39+
# Once implemented, change fibonacci (above) to call fibonacci_dynamic
40+
# to verify that your dynamic implementation passes all test cases
41+
42+
43+
def main():
44+
import sys
45+
args = sys.argv[1:] # Ignore script file name
46+
if len(args) == 1:
47+
num = int(args[0])
48+
result = fibonacci(num)
49+
print('fibonacci({}) => {}'.format(num, result))
50+
else:
51+
print('Usage: {} number'.format(sys.argv[0]))
52+
53+
54+
if __name__ == '__main__':
55+
main()

Diff for: source/recursion_test.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!python
2+
3+
from recursion import fibonacci
4+
import unittest
5+
6+
7+
class RecursionTest(unittest.TestCase):
8+
def test_fibonacci_with_small_integers(self):
9+
# Known fibonacci numbers with small integer arguments
10+
assert fibonacci(0) == 0 # base case
11+
assert fibonacci(1) == 1 # base case
12+
assert fibonacci(2) == 1
13+
assert fibonacci(3) == 2
14+
assert fibonacci(4) == 3
15+
assert fibonacci(5) == 5
16+
assert fibonacci(6) == 8
17+
assert fibonacci(7) == 13
18+
assert fibonacci(8) == 21
19+
assert fibonacci(9) == 34
20+
assert fibonacci(10) == 55
21+
22+
def test_fibonacci_with_large_integers(self):
23+
# These could run for a long time, depending on your implementation...
24+
assert fibonacci(15) == 610
25+
assert fibonacci(20) == 6765
26+
assert fibonacci(25) == 75025
27+
# TODO: Improve the runtime of your fibonacci function for these cases
28+
# If you're not careful, you may need to be very patient for these...
29+
# assert fibonacci(30) == 832040
30+
# assert fibonacci(35) == 9227465
31+
# assert fibonacci(40) == 102334155
32+
33+
def test_fibonacci_with_negative_integers(self):
34+
# Should raise a ValueError for n < 0
35+
with self.assertRaises(ValueError):
36+
fibonacci(-1)
37+
with self.assertRaises(ValueError):
38+
fibonacci(-5)
39+
40+
def test_fibonacci_with_floating_point_numbers(self):
41+
# Should raise a ValueError for non-integer n
42+
with self.assertRaises(ValueError):
43+
fibonacci(2.0)
44+
with self.assertRaises(ValueError):
45+
fibonacci(3.14159)
46+
with self.assertRaises(ValueError):
47+
fibonacci('5')
48+
49+
50+
if __name__ == '__main__':
51+
unittest.main()

0 commit comments

Comments
 (0)