Skip to content

Commit 33fc0c7

Browse files
recursion prep
1 parent 7d0bd26 commit 33fc0c7

37 files changed

Lines changed: 917 additions & 326 deletions

3_documenting_and_testing/exercises/mystery_5.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
def mystery_5(a, b=None):
2-
if b is None:
3-
b = []
1+
def mystery_5(a, b):
42
while a:
53
c = min(a)
64
a.remove(c)

3_documenting_and_testing/exercises/tests/test_mystery_5.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,4 @@ class TestMystery5(unittest.TestCase):
88
def test_minimal_input(self):
99
""""""
1010
self.assertEqual(mystery_5([], []), [])
11-
12-
def test_minimal_input_none(self):
13-
""""""
14-
self.assertEqual(mystery_5([], None), [])
15-
16-
def test_minimal_input_default_argument(self):
17-
""""""
18-
self.assertEqual(mystery_5([]), [])
11+

6_recursion/1_describe_recursion/README.md

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ You can also summarize a recursive strategy in a few lines like so:
2222

2323
```py
2424
"""
25-
base case -> turn-around
26-
recursive case -> ƒ(break-down) + rest of solution
25+
behavior description
26+
27+
base case :
28+
argument description -> turn-around description
29+
recursive case:
30+
argument description -> ƒ(break-down description) build-up description
2731
"""
2832
```
2933

@@ -40,8 +44,12 @@ connect your programming knowledge to computer science principles.
4044
```py
4145
def _func_name_(__: __) -> __:
4246
"""
43-
base case -> return value
44-
recursive case -> ƒ(break-down) + rest of solution
47+
behavior description
48+
49+
base case :
50+
argument description -> turn-around description
51+
recursive case:
52+
argument description -> ƒ(break-down description) build-up description
4553
"""
4654
is_base_case = __ # must use argument(s)
4755
if is_base_case:
@@ -65,8 +73,12 @@ solution, the more it resembles the semi-formal description.
6573

6674
def reverse_string(to_reverse: str) -> str:
6775
"""
68-
empty string -> empty string
69-
non-empty str -> ƒ(string without first char) + first char
76+
Reverses the characters in a string.
77+
78+
base case :
79+
empty string -> empty string
80+
recursive case:
81+
non-empty str -> ƒ(string without first char) + first char
7082
"""
7183
is_base_case = len(to_reverse) == 0 # must use argument(s)
7284
if is_base_case:
@@ -84,8 +96,12 @@ def reverse_string(to_reverse: str) -> str:
8496

8597
def reverse_string(to_reverse: str) -> str:
8698
"""
87-
empty string -> empty string
88-
non-empty str -> ƒ(string without first char) + first char
99+
Reverses the characters in a string.
100+
101+
base case :
102+
empty string -> empty string
103+
recursive case:
104+
non-empty str -> ƒ(string without first char) + first char
89105
"""
90106
if len(to_reverse) == 0: # base case
91107
return '' # turn-around
@@ -101,8 +117,12 @@ def reverse_string(to_reverse: str) -> str:
101117

102118
def reverse_string(to_reverse: str) -> str:
103119
"""
104-
empty string -> empty string
105-
non-empty str -> ƒ(string without first char) + first char
120+
Reverses the characters in a string.
121+
122+
base case :
123+
empty string -> empty string
124+
recursive case:
125+
non-empty str -> ƒ(string without first char) + first char
106126
"""
107127
if len(to_reverse) == 0: # base case
108128
return '' # turn-around
@@ -116,8 +136,12 @@ def reverse_string(to_reverse: str) -> str:
116136

117137
def reverse_string(to_reverse: str) -> str:
118138
"""
119-
empty string -> empty string
120-
non-empty str -> ƒ(string without first char) + first char
139+
Reverses the characters in a string.
140+
141+
base case :
142+
empty string -> empty string
143+
recursive case:
144+
non-empty str -> ƒ(string without first char) + first char
121145
"""
122146
if len(to_reverse) == 0:
123147
return ''

6_recursion/1_describe_recursion/examples/1_linear_recursion.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def reverse_list(to_reverse: list) -> list:
2828

2929
# --- --- --- test cases --- --- ---
3030

31-
assert reverse_list([]) == [], "Test 1"
32-
assert reverse_list([1, 2, 3]) == [3, 2, 1], "Test 2"
33-
assert reverse_list([1, 2, 1]) == [1, 2, 1], "Test 3"
34-
assert reverse_list(["", False, None, 0]) == [0, None, False, ""], "Test 4"
31+
print(reverse_list([]), "should be", [])
32+
print(reverse_list([1, 2, 3]), "should be", [3, 2, 1])
33+
print(reverse_list([1, 2, 1]), "should be", [1, 2, 1])
34+
print(reverse_list(["", False, None, 0]), "should be", [0, None, False, ""])

6_recursion/1_describe_recursion/examples/2_tree_recursion.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ def fibonacci(n: int) -> int:
3737

3838
# --- --- --- test cases --- --- ---
3939

40-
assert fibonacci(0) == 0, "0 -> 0"
41-
assert fibonacci(1) == 1, "1 -> 1"
42-
assert fibonacci(2) == 1, "2 -> 1"
43-
assert fibonacci(3) == 2, "3 -> 2"
44-
assert fibonacci(4) == 3, "4 -> 3"
45-
assert fibonacci(5) == 5, "5 -> 5"
46-
assert fibonacci(6) == 8, "6 -> 8"
47-
assert fibonacci(7) == 13, "7 -> 13"
48-
# assert fibonacci(33) == 3524578, '7 -> 3524578' # a slow line!
40+
print(fibonacci(0) , 'should be ', 0)
41+
print(fibonacci(1) , 'should be ', 1)
42+
print(fibonacci(2) , 'should be ', 1)
43+
print(fibonacci(3) , 'should be ', 2)
44+
print(fibonacci(4) , 'should be ', 3)
45+
print(fibonacci(5) , 'should be ', 5)
46+
print(fibonacci(6) , 'should be ', 8)
47+
print(fibonacci(7) , 'should be ', 13)
48+
# print(fibonacci(33) , 'should be ', 3524578) # a slow line!

6_recursion/1_describe_recursion/exercises/fibonacci_memo.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,22 @@ def fibonacci(n: int, memo: dict = {}) -> int:
1717
recursive case:
1818
1919
"""
20-
if n == 0:
21-
return 0
22-
23-
if n == 1:
24-
return 1
25-
26-
if n in memo:
27-
return memo[n]
28-
29-
memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo)
20+
if n == 0: #
21+
return 0 #
22+
23+
if n == 1: #
24+
return 1 #
25+
26+
if n in memo: #
27+
return memo[n] #
28+
29+
#
30+
left_recursion = fibonacci(n - 1, memo)
31+
#
32+
right_recursion = fibonacci(n - 2, memo)
33+
#
34+
memo[n] = left_recursion + right_recursion
35+
3036
return memo[n]
3137

3238

6_recursion/1_describe_recursion/exercises/merge_sort.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ def merge_sort(numbers: list) -> list:
1717
return numbers #
1818

1919
mid = len(numbers) // 2
20-
# |
20+
#
2121
left_half = merge_sort(numbers[:mid])
22-
# |
22+
#
2323
right_half = merge_sort(numbers[mid:])
2424

2525
return merge(left_half, right_half)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
""" Use test cases, the docstring, and labels to describe this solution. """
5+
6+
7+
def reverse_list(to_reverse: list) -> list:
8+
"""
9+
10+
11+
base case:
12+
13+
recursive case:
14+
15+
"""
16+
if len(to_reverse) == 0: #
17+
return [] #
18+
19+
#
20+
return reverse_list(to_reverse[1:]) + [to_reverse[0]]
21+
22+
23+
# --- call the traced function ---
24+
25+
print(reverse_list([]), 'should be', [])
26+
print(reverse_list([1, 2, 3]), 'should be', [3, 2, 1])
27+
print(reverse_list([1, 2, 1]), 'should be', [1, 2, 1])
28+
print(reverse_list(["", False, None, 0]), 'should be', [0, None, False, ""])

6_recursion/1_describe_recursion/exercises/sum_digits_to_threshold.py

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
""" Visualizing count_items
5+
6+
To visualize implementation,
7+
- use your VSCode debugger
8+
- copy-paste the code into PythonTutor
9+
10+
To visualize strategy:
11+
- run the script and read the recursion trace
12+
- comment @trace_recursion and debug the function
13+
or copy the function into one of these sites:
14+
- https://www.recursionvisualizer.com
15+
- (https://recursion.vercel.app
16+
- https://recursion-visualizer.vercel.app
17+
- https://visualgo.net/en/recursion
18+
19+
"""
20+
21+
import sys
22+
import os
23+
24+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
25+
26+
from trace_recursion import trace_recursion
27+
28+
29+
@trace_recursion
30+
def count_items(to_count: list) -> int:
31+
"""
32+
33+
"""
34+
if len(to_count) == 0:
35+
return 0
36+
37+
break_down = to_count[1:]
38+
recursion = count_items(break_down)
39+
build_up = recursion + 1
40+
41+
return build_up
42+
43+
44+
# --- call the traced function ---
45+
46+
print(count_items([]), 'should be', 0)
47+
print(count_items([1, 2, 3]), 'should be', 3)
48+
print(count_items([1, 2, 1]), 'should be', 3)
49+
print(count_items(["", False, None, 0]), 'should be', 4)
50+
print(count_items(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']), 'should be', 8)

0 commit comments

Comments
 (0)