Common Algorithms
Recursion Examples
Real-world applications frequently need to process nested data structures, calculate mathematical sequences, or search through hierarchical information. This page demonstrates practical recursive algorithms that solve common programming challenges like summing lists, reversing strings, and computing greatest common divisors.
This page demonstrates practical applications of recursion beyond the basic factorial and Fibonacci examples.
Common Patterns
- List processing: recursively process each element
- String manipulation: work on substring recursively
- Mathematical computations: divide problem into parts
- Tree traversal: process node, recurse on children
Key Techniques
- Head recursion: recursive call before processing
- Tail recursion: recursive call as last operation
- Multiple recursion: multiple recursive calls
- Helper functions: wrapper with extra parameters
head_recursion
Recursive call happens before processing the current element
tail_recursion
Recursive call is the last operation, enabling potential optimization
Sum of List
list_sum.py
Replay: real traced execution (multi-file project)
# Recursive sum of list
def sum_list(lst):
"""Sum list recursively"""
# Base case: empty list
if not lst:
return 0
# Recursive case: first + sum of rest
return lst[0] + sum_list(lst[1:])
def sum_by_index(lst, index=0):
"""Sum using index parameter"""
# Base case: reached end
if index >= len(lst):
return 0
# Recursive: current + rest
return lst[index] + sum_by_index(lst, index + 1)
def sum_tail_recursive(lst, accumulator=0):
"""Tail recursive sum"""
# Base case
if not lst:
return accumulator
# Tail recursion: recursive call is last operation
return sum_tail_recursive(lst[1:], accumulator + lst[0])
# Test list sum
numbers = [1, 2, 3, 4, 5]
print("List:", numbers)
print("Sum (basic): ", sum_list(numbers))
print("Sum (index): ", sum_by_index(numbers))
print("Sum (tail): ", sum_tail_recursive(numbers))
values = [10, 20, 30, 40]
print("\nList:", values)
print("Sum:", sum_list(values))
# Recursive sum of list
def sum_list(lst):
"""Sum list recursively"""
# Base case: empty list
if not lst:
return 0
# Recursive case: first + sum of rest
return lst[0] + sum_list(lst[1:])
def sum_by_index(lst, index=0):
"""Sum using index parameter"""
# Base case: reached end
if index >= len(lst):
return 0
# Recursive: current + rest
return lst[index] + sum_by_index(lst, index + 1)
def sum_tail_recursive(lst, accumulator=0):
"""Tail recursive sum"""
# Base case
if not lst:
return accumulator
# Tail recursion: recursive call is last operation
return sum_tail_recursive(lst[1:], accumulator + lst[0])
# Test list sum
numbers = [2, 4, 6]
print("List:", numbers)
print("Sum (basic): ", sum_list(numbers))
print("Sum (index): ", sum_by_index(numbers))
print("Sum (tail): ", sum_tail_recursive(numbers))
values = [10, 20, 30, 40]
print("\nList:", values)
print("Sum:", sum_list(values))
# Recursive sum of list
def sum_list(lst):
"""Sum list recursively"""
# Base case: empty list
if not lst:
return 0
# Recursive case: first + sum of rest
return lst[0] + sum_list(lst[1:])
def sum_by_index(lst, index=0):
"""Sum using index parameter"""
# Base case: reached end
if index >= len(lst):
return 0
# Recursive: current + rest
return lst[index] + sum_by_index(lst, index + 1)
def sum_tail_recursive(lst, accumulator=0):
"""Tail recursive sum"""
# Base case
if not lst:
return accumulator
# Tail recursion: recursive call is last operation
return sum_tail_recursive(lst[1:], accumulator + lst[0])
# Test list sum
numbers = [10, -5, 15]
print("List:", numbers)
print("Sum (basic): ", sum_list(numbers))
print("Sum (index): ", sum_by_index(numbers))
print("Sum (tail): ", sum_tail_recursive(numbers))
values = [10, 20, 30, 40]
print("\nList:", values)
print("Sum:", sum_list(values))
numbers ← [1, 2, 3, 4, 5]
34# Test list sum35numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]36#@numbers=[2, 4, 6], [10, -5, 15]3738print("List:", numbers[1, 2, 3, 4, 5])39print("Sum (basic): ", sum_list(numbers[1, 2, 3, 4, 5]))40print("Sum (index): ", sum_by_index(numbers))outputList: [1, 2, 3, 4, 5]def sum_list(lst):
pass 1 of 114def sum_list(lst[1, 2, 3, 4, 5]):5 """Sum list recursively"""6 # Base case: empty list7 if not lst:8 return 0910 # Recursive case: first + sum of rest11 return lst[0]1 + sum_list(lst[1:][2, 3, 4, 5])All 11 passes — pass 1 is the card above pass lstlst[0]lst[1:]1 [1, 2, 3, 4, 5] 1 [2, 3, 4, 5] 2 [2, 3, 4, 5] 2 [3, 4, 5] 3 [3, 4, 5] 3 [4, 5] 4 [4, 5] 4 [5] 5 [5] 5 [] 6 [] — — 7 [10, 20, 30, 40] 10 [20, 30, 40] 8 [20, 30, 40] 20 [30, 40] 9 [30, 40] 30 [40] 10 [40] 40 [] 11 [] — — if not lst:
pass 1 of 26# Base case: empty list7if not lst[]:8 return 0print("Sum (basic): ", sum_list(numbers))
38print("List:", numbers)39print("Sum (basic): ", sum_list(numbers[1, 2, 3, 4, 5]))40print("Sum (index): ", sum_by_index(numbers[1, 2, 3, 4, 5]))41print("Sum (tail): ", sum_tail_recursive(numbers))outputSum (basic): 15def sum_by_index(lst, index=0):
pass 1 of 614def sum_by_index(lst[1, 2, 3, 4, 5], index0=0):15 """Sum using index parameter"""16 # Base case: reached end17 if index >= len(lst):18 return 01920 # Recursive: current + rest21 return lst[index]1 + sum_by_index(lst[1, 2, 3, 4, 5], index0 + 1)All 6 passes — pass 1 is the card above pass indexlst[index]1 0 1 2 1 2 3 2 3 4 3 4 5 4 5 6 5 — if index >= len(lst):
16# Base case: reached end17if index5 >= len(lst[1, 2, 3, 4, 5]):18 return 0print("Sum (index): ", sum_by_index(numbers))
39print("Sum (basic): ", sum_list(numbers))40print("Sum (index): ", sum_by_index(numbers[1, 2, 3, 4, 5]))41print("Sum (tail): ", sum_tail_recursive(numbers[1, 2, 3, 4, 5]))outputSum (index): 15def sum_tail_recursive(lst, accumulator=0):
pass 1 of 624def sum_tail_recursive(lst[1, 2, 3, 4, 5], accumulator0=0):25 """Tail recursive sum"""26 # Base case27 if not lst:28 return accumulator2930 # Tail recursion: recursive call is last operation31 return sum_tail_recursive(lst[1:][2, 3, 4, 5], accumulator0 + lst[0]1)All 6 passes — pass 1 is the card above pass lstaccumulatorlst[1:]lst[0]1 [1, 2, 3, 4, 5] 0 [2, 3, 4, 5] 1 2 [2, 3, 4, 5] 1 [3, 4, 5] 2 3 [3, 4, 5] 3 [4, 5] 3 4 [4, 5] 6 [5] 4 5 [5] 10 [] 5 6 [] 15 — — if not lst:
26# Base case27if not lst[]:28 return accumulator15values ← [10, 20, 30, 40]
40print("Sum (index): ", sum_by_index(numbers))41print("Sum (tail): ", sum_tail_recursive(numbers[1, 2, 3, 4, 5]))4243values→ [10, 20, 30, 40] = [10, 20, 30, 40]44print("\nList:", values[10, 20, 30, 40])45print("Sum:", sum_list(values[10, 20, 30, 40]))outputSum (tail): 15 List: [10, 20, 30, 40]if not lst:
pass 2 of 26# Base case: empty list7if not lst[]:8 return 0print("Sum:", sum_list(values))
44print("\nList:", values)45print("Sum:", sum_list(values[10, 20, 30, 40]))outputSum: 100
numbers ← [2, 4, 6]
34# Test list sum35numbers→ [2, 4, 6] = [2, 4, 6]3637print("List:", numbers[2, 4, 6])38print("Sum (basic): ", sum_list(numbers[2, 4, 6]))39print("Sum (index): ", sum_by_index(numbers))outputList: [2, 4, 6]def sum_list(lst):
pass 1 of 94def sum_list(lst[2, 4, 6]):5 """Sum list recursively"""6 # Base case: empty list7 if not lst:8 return 0910 # Recursive case: first + sum of rest11 return lst[0]2 + sum_list(lst[1:][4, 6])All 9 passes — pass 1 is the card above pass lstlst[0]lst[1:]1 [2, 4, 6] 2 [4, 6] 2 [4, 6] 4 [6] 3 [6] 6 [] 4 [] — — 5 [10, 20, 30, 40] 10 [20, 30, 40] 6 [20, 30, 40] 20 [30, 40] 7 [30, 40] 30 [40] 8 [40] 40 [] 9 [] — — if not lst:
pass 1 of 26# Base case: empty list7if not lst[]:8 return 0print("Sum (basic): ", sum_list(numbers))
37print("List:", numbers)38print("Sum (basic): ", sum_list(numbers[2, 4, 6]))39print("Sum (index): ", sum_by_index(numbers[2, 4, 6]))40print("Sum (tail): ", sum_tail_recursive(numbers))outputSum (basic): 12def sum_by_index(lst, index=0):
pass 1 of 414def sum_by_index(lst[2, 4, 6], index0=0):15 """Sum using index parameter"""16 # Base case: reached end17 if index >= len(lst):18 return 01920 # Recursive: current + rest21 return lst[index]2 + sum_by_index(lst[2, 4, 6], index0 + 1)All 4 passes — pass 1 is the card above pass indexlst[index]1 0 2 2 1 4 3 2 6 4 3 — if index >= len(lst):
16# Base case: reached end17if index3 >= len(lst[2, 4, 6]):18 return 0print("Sum (index): ", sum_by_index(numbers))
38print("Sum (basic): ", sum_list(numbers))39print("Sum (index): ", sum_by_index(numbers[2, 4, 6]))40print("Sum (tail): ", sum_tail_recursive(numbers[2, 4, 6]))outputSum (index): 12def sum_tail_recursive(lst, accumulator=0):
pass 1 of 424def sum_tail_recursive(lst[2, 4, 6], accumulator0=0):25 """Tail recursive sum"""26 # Base case27 if not lst:28 return accumulator2930 # Tail recursion: recursive call is last operation31 return sum_tail_recursive(lst[1:][4, 6], accumulator0 + lst[0]2)All 4 passes — pass 1 is the card above pass lstaccumulatorlst[1:]lst[0]1 [2, 4, 6] 0 [4, 6] 2 2 [4, 6] 2 [6] 4 3 [6] 6 [] 6 4 [] 12 — — if not lst:
26# Base case27if not lst[]:28 return accumulator12values ← [10, 20, 30, 40]
39print("Sum (index): ", sum_by_index(numbers))40print("Sum (tail): ", sum_tail_recursive(numbers[2, 4, 6]))4142values→ [10, 20, 30, 40] = [10, 20, 30, 40]43print("\nList:", values[10, 20, 30, 40])44print("Sum:", sum_list(values[10, 20, 30, 40]))outputSum (tail): 12 List: [10, 20, 30, 40]if not lst:
pass 2 of 26# Base case: empty list7if not lst[]:8 return 0print("Sum:", sum_list(values))
43print("\nList:", values)44print("Sum:", sum_list(values[10, 20, 30, 40]))outputSum: 100
numbers ← [10, -5, 15]
34# Test list sum35numbers→ [10, -5, 15] = [10, -5, 15]3637print("List:", numbers[10, -5, 15])38print("Sum (basic): ", sum_list(numbers[10, -5, 15]))39print("Sum (index): ", sum_by_index(numbers))outputList: [10, -5, 15]def sum_list(lst):
pass 1 of 94def sum_list(lst[10, -5, 15]):5 """Sum list recursively"""6 # Base case: empty list7 if not lst:8 return 0910 # Recursive case: first + sum of rest11 return lst[0]10 + sum_list(lst[1:][-5, 15])All 9 passes — pass 1 is the card above pass lstlst[0]lst[1:]1 [10, -5, 15] 10 [-5, 15] 2 [-5, 15] -5 [15] 3 [15] 15 [] 4 [] — — 5 [10, 20, 30, 40] 10 [20, 30, 40] 6 [20, 30, 40] 20 [30, 40] 7 [30, 40] 30 [40] 8 [40] 40 [] 9 [] — — if not lst:
pass 1 of 26# Base case: empty list7if not lst[]:8 return 0print("Sum (basic): ", sum_list(numbers))
37print("List:", numbers)38print("Sum (basic): ", sum_list(numbers[10, -5, 15]))39print("Sum (index): ", sum_by_index(numbers[10, -5, 15]))40print("Sum (tail): ", sum_tail_recursive(numbers))outputSum (basic): 20def sum_by_index(lst, index=0):
pass 1 of 414def sum_by_index(lst[10, -5, 15], index0=0):15 """Sum using index parameter"""16 # Base case: reached end17 if index >= len(lst):18 return 01920 # Recursive: current + rest21 return lst[index]10 + sum_by_index(lst[10, -5, 15], index0 + 1)All 4 passes — pass 1 is the card above pass indexlst[index]1 0 10 2 1 -5 3 2 15 4 3 — if index >= len(lst):
16# Base case: reached end17if index3 >= len(lst[10, -5, 15]):18 return 0print("Sum (index): ", sum_by_index(numbers))
38print("Sum (basic): ", sum_list(numbers))39print("Sum (index): ", sum_by_index(numbers[10, -5, 15]))40print("Sum (tail): ", sum_tail_recursive(numbers[10, -5, 15]))outputSum (index): 20def sum_tail_recursive(lst, accumulator=0):
pass 1 of 424def sum_tail_recursive(lst[10, -5, 15], accumulator0=0):25 """Tail recursive sum"""26 # Base case27 if not lst:28 return accumulator2930 # Tail recursion: recursive call is last operation31 return sum_tail_recursive(lst[1:][-5, 15], accumulator0 + lst[0]10)All 4 passes — pass 1 is the card above pass lstaccumulatorlst[1:]lst[0]1 [10, -5, 15] 0 [-5, 15] 10 2 [-5, 15] 10 [15] -5 3 [15] 5 [] 15 4 [] 20 — — if not lst:
26# Base case27if not lst[]:28 return accumulator20values ← [10, 20, 30, 40]
39print("Sum (index): ", sum_by_index(numbers))40print("Sum (tail): ", sum_tail_recursive(numbers[10, -5, 15]))4142values→ [10, 20, 30, 40] = [10, 20, 30, 40]43print("\nList:", values[10, 20, 30, 40])44print("Sum:", sum_list(values[10, 20, 30, 40]))outputSum (tail): 20 List: [10, 20, 30, 40]if not lst:
pass 2 of 26# Base case: empty list7if not lst[]:8 return 0print("Sum:", sum_list(values))
43print("\nList:", values)44print("Sum:", sum_list(values[10, 20, 30, 40]))outputSum: 100
list_recursion
Process the first element, then recursively handle the rest of the list
Reverse String
string_reverse.py
Replay: real traced execution (multi-file project)
# Recursive string reverse
def reverse(s):
"""Reverse using substring"""
# Base case: empty or single character
if len(s) <= 1:
return s
# Recursive: last char + reverse of rest
return s[-1] + reverse(s[:-1])
def reverse_alt(s):
"""Alternative: first char at end"""
# Base case
if len(s) <= 1:
return s
# Recursive: reverse rest + first char
return reverse_alt(s[1:]) + s[0]
def reverse_trace(s, depth=0):
"""Reverse with trace"""
indent = " " * depth
print(f"{indent}reverse(\"{s}\")")
# Base and recursive cases
if len(s) <= 1:
print(f"{indent} → \"{s}\"")
return s
last = s[-1]
rest = s[:-1]
result = last + reverse_trace(rest, depth + 1)
print(f"{indent} → \"{result}\"")
return result
# Test string reverse
words = ["hello", "recursion", "Python"]
for word in words:
print(f"{word} → {reverse(word)}")
print("\nAlternative approach:")
print(f"world → {reverse_alt('world')}")
print("\nWith trace:")
reverse_trace("abc")
words ← ['hello', 'recursion', 'Python']
42# Test string reverse43words→ ['hello', 'recursion', 'Python'] = ["hello", "recursion", "Python"]for word in words:
pass 1 of 345for wordhello in words['hello', 'recursion', 'Python']:46 print(f"{wordhello} → {reverse(word)}")All 3 passes — pass 1 is the card above pass word1 hello 2 recursion 3 Python def reverse(s):
pass 1 of 204def reverse(shello):5 """Reverse using substring"""6 # Base case: empty or single character7 if len(s) <= 1:8 return s910 # Recursive: last char + reverse of rest11 return s[-1]o + reverse(s[:-1]hell)20 passes — pass 1 is the card above pass ss[-1]s[:-1]1 hello o hell 2 hell l hel 3 hel l he 4 he e h 5 h — — 6 recursion n recursio 7 recursio o recursi 8 recursi i recurs 9 recurs s recur ⋯ 9 more passes ⋯ 19 Py y P 20 P — — if len(s) <= 1:
pass 1 of 36# Base case: empty or single character7if len(sh) <= 1:8 return shAll 3 passes — pass 1 is the card above pass s1 h 2 r 3 P print(f"{word} → {reverse(word)}")
45for word in words:46 print(f"{wordhello} → {reverse(word)}")outputhello → ollehprint(f"{word} → {reverse(word)}")
45for word in words:46 print(f"{wordrecursion} → {reverse(word)}")outputrecursion → noisrucerprint(f"{word} → {reverse(word)}")
45for word in words:46 print(f"{wordPython} → {reverse(word)}")outputPython → nohtyPprint(" Alternative approach:")
48print("\nAlternative approach:")49print(f"world → {reverse_alt('world')}")output Alternative approach:def reverse_alt(s):
pass 1 of 514def reverse_alt(sworld):15 """Alternative: first char at end"""16 # Base case17 if len(s) <= 1:18 return s1920 # Recursive: reverse rest + first char21 return reverse_alt(s[1:]orld) + s[0]wAll 5 passes — pass 1 is the card above pass ss[1:]s[0]1 world orld w 2 orld rld o 3 rld ld r 4 ld d l 5 d — — if len(s) <= 1:
16# Base case17if len(sd) <= 1:18 return sdprint(f"world → {reverse_alt('world')}")
48print("\nAlternative approach:")49print(f"world → {reverse_alt('world')}")5051print("\nWith trace:")52reverse_trace("abc")outputworld → dlrow With trace:indent ← (empty), last ← c, rest ← ab
pass 1 of 324def reverse_trace(sabc, depth0=0):25 """Reverse with trace"""26 indent→ (empty) = " " * depth027 print(f"{indent(empty)}reverse(\"{sabc}\")")2829 # Base and recursive cases30 if len(s) <= 1:31 print(f"{indent} → \"{s}\"")32 return s3334 last→ c = s[-1]c35 rest→ ab = s[:-1]ab36 result = lastc + reverse_trace(restab, depth0 + 1)outputreverse("abc")All 3 passes — pass 1 is the card above pass sdepths[-1]s[:-1]indentlastrest1 abc 0 c ab (empty) c ab 2 ab 1 b a b a 3 a 2 — — — — if len(s) <= 1:
29# Base and recursive cases30if len(sa) <= 1:31 print(f"{indent } → \"{sa}\"")32 return saoutput → "a"result ← ba
35rest = s[:-1]36result→ ba = lastb + reverse_trace(resta, depth1 + 1)3738print(f"{indent } → \"{resultba}\"")39return resultbaoutput → "ba"last ← c, rest ← ab, depth ← 0, result ← cba
35rest = s[:-1]36result→ cba = last→ c + reverse_trace(rest→ ab, depth→ 0 + 1)3738print(f"{indent(empty)} → \"{resultcba}\"")39return resultcbaoutput → "cba"reverse_trace("abc")
51print("\nWith trace:")52reverse_trace("abc")
Power Function
power.py
Replay: real traced execution (multi-file project)
# Recursive power function
def power(base, exp):
"""Simple recursive power"""
# Base case
if exp == 0:
return 1
# Recursive case: base * base^(exp-1)
return base * power(base, exp - 1)
def power_optimized(base, exp):
"""Optimized: divide and conquer"""
# Base case
if exp == 0:
return 1
# If even: (base^(exp/2))^2
if exp % 2 == 0:
half = power_optimized(base, exp // 2)
return half * half
# If odd: base * base^(exp-1)
return base * power_optimized(base, exp - 1)
# Count calls
call_count = 0
def power_counted(base, exp):
"""Power with call counting"""
global call_count
call_count += 1
if exp == 0:
return 1
return base * power_counted(base, exp - 1)
def power_optimized_counted(base, exp):
"""Optimized power with call counting"""
global call_count
call_count += 1
if exp == 0:
return 1
if exp % 2 == 0:
half = power_optimized_counted(base, exp // 2)
return half * half
return base * power_optimized_counted(base, exp - 1)
# Test power functions
print(f"2^10 = {power(2, 10)}")
print(f"3^5 = {power(3, 5)}")
print("\nOptimized:")
print(f"2^10 = {power_optimized(2, 10)}")
# Compare call counts
call_count = 0
r1 = power_counted(2, 10)
calls1 = call_count
call_count = 0
r2 = power_optimized_counted(2, 10)
calls2 = call_count
print("\nCalls for 2^10:")
print(f" Simple: {calls1} calls")
print(f" Optimized: {calls2} calls")
call_count ← 0
29# Count calls30call_count→ 0 = 0313233def power_counted(base, exp):34 """Power with call counting"""35 global call_count36 call_count += 13738 if exp == 0:39 return 140 return base * power_counted(base, exp - 1)414243def power_optimized_counted(base, exp):44 """Optimized power with call counting"""45 global call_count46 call_count += 14748 if exp == 0:49 return 150 if exp % 2 == 0:51 half = power_optimized_counted(base, exp // 2)52 return half * half53 return base * power_optimized_counted(base, exp - 1)545556# Test power functions57print(f"2^10 = {power(2, 10)}")58print(f"3^5 = {power(3, 5)}")def power(base, exp):
pass 1 of 174def power(base2, exp10):5 """Simple recursive power"""6 # Base case7 if exp == 0:8 return 1910 # Recursive case: base * base^(exp-1)11 return base2 * power(base, exp10 - 1)17 passes — pass 1 is the card above pass baseexp1 2 10 2 2 9 3 2 8 4 2 7 5 2 6 6 2 5 7 2 4 8 2 3 9 2 2 ⋯ 6 more passes ⋯ 16 3 1 17 3 0 if exp == 0:
pass 1 of 26# Base case7if exp0 == 0:8 return 1print(f"2^10 = {power(2, 10)}")
56# Test power functions57print(f"2^10 = {power(2, 10)}")58print(f"3^5 = {power(3, 5)}")output2^10 = 1024if exp == 0:
pass 2 of 26# Base case7if exp0 == 0:8 return 1print(f"3^5 = {power(3, 5)}")
57print(f"2^10 = {power(2, 10)}")58print(f"3^5 = {power(3, 5)}")5960print("\nOptimized:")61print(f"2^10 = {power_optimized(2, 10)}")output3^5 = 243 Optimized:def power_optimized(base, exp):
pass 1 of 614def power_optimized(base2, exp10):15 """Optimized: divide and conquer"""16 # Base caseAll 6 passes — pass 1 is the card above pass exp1 10 2 5 3 4 4 2 5 1 6 0 if exp % 2 == 0:
pass 1 of 320# If even: (base^(exp/2))^221if exp10 % 2 == 0:22 half = power_optimized(base2, exp10 // 2)23 return half * halfAll 3 passes — pass 1 is the card above pass exp1 10 2 4 3 2 if exp == 0:
16# Base case17if exp0 == 0:18 return 1half ← 2
21if exp % 2 == 0:22 half→ 2 = power_optimized(base2, exp2 // 2)23 return half2 * halfbase ← 2, exp ← 4, half ← 4
21if exp % 2 == 0:22 half→ 4 = power_optimized(base→ 2, exp→ 4 // 2)23 return half4 * halfbase ← 2, exp ← 10, half ← 32
21if exp % 2 == 0:22 half→ 32 = power_optimized(base→ 2, exp→ 10 // 2)23 return half32 * halfcall_count ← 0
60print("\nOptimized:")61print(f"2^10 = {power_optimized(2, 10)}")6263# Compare call counts64call_count→ 0 = 065r1 = power_counted(2, 10)66calls1 = call_countoutput2^10 = 1024call_count ← 1
pass 1 of 1133def power_counted(base2, exp10):34 """Power with call counting"""35 global call_count36 call_count→ 1 += 13738 if exp == 0:39 return 140 return base2 * power_counted(base, exp10 - 1)All 11 passes — pass 1 is the card above pass expcall_count1 10 0 → 1 2 9 1 → 2 3 8 2 → 3 4 7 3 → 4 5 6 4 → 5 6 5 5 → 6 7 4 6 → 7 8 3 7 → 8 9 2 8 → 9 10 1 9 → 10 11 0 10 → 11 if exp == 0:
38if exp0 == 0:39 return 140return base * power_counted(base, exp - 1)r1 ← 1024, calls1 ← 11, call_count ← 0
64call_count = 065r1→ 1024 = power_counted(2, 10)66calls1→ 11 = call_count116768call_count→ 0 = 069r2 = power_optimized_counted(2, 10)70calls2 = call_countcall_count ← 1
pass 1 of 643def power_optimized_counted(base2, exp10):44 """Optimized power with call counting"""45 global call_count46 call_count→ 1 += 1All 6 passes — pass 1 is the card above pass expcall_count1 10 0 → 1 2 5 1 → 2 3 4 2 → 3 4 2 3 → 4 5 1 4 → 5 6 0 5 → 6 if exp % 2 == 0:
pass 1 of 349 return 150if exp10 % 2 == 0:51 half = power_optimized_counted(base2, exp10 // 2)52 return half * halfAll 3 passes — pass 1 is the card above pass exp1 10 2 4 3 2 if exp == 0:
48if exp0 == 0:49 return 150if exp % 2 == 0:half ← 2
50if exp % 2 == 0:51 half→ 2 = power_optimized_counted(base2, exp2 // 2)52 return half2 * half53return base * power_optimized_counted(base, exp - 1)base ← 2, exp ← 4, half ← 4
50if exp % 2 == 0:51 half→ 4 = power_optimized_counted(base→ 2, exp→ 4 // 2)52 return half4 * half53return base * power_optimized_counted(base, exp - 1)base ← 2, exp ← 10, half ← 32
50if exp % 2 == 0:51 half→ 32 = power_optimized_counted(base→ 2, exp→ 10 // 2)52 return half32 * half53return base * power_optimized_counted(base, exp - 1)r2 ← 1024, calls2 ← 6
68call_count = 069r2→ 1024 = power_optimized_counted(2, 10)70calls2→ 6 = call_count67172print("\nCalls for 2^10:")73print(f" Simple: {calls111} calls")74print(f" Optimized: {calls26} calls")output Calls for 2^10: Simple: 11 calls Optimized: 6 calls
divide_conquer
Break the problem in half to achieve O(log n) instead of O(n)
Count Occurrences
count.py
Replay: real traced execution (multi-file project)
# Count occurrences
def count_in_list(lst, target):
"""Count value in list"""
# Base case: empty list
if not lst:
return 0
# Check first element
current_count = 1 if lst[0] == target else 0
# Add count from rest
return current_count + count_in_list(lst[1:], target)
def count_char(s, target):
"""Count char in string"""
# Base case: empty string
if not s:
return 0
# Check first character
current_count = 1 if s[0] == target else 0
# Add count from rest
return current_count + count_char(s[1:], target)
def count_digits(n):
"""Count digits in number"""
# Base case: single digit
if n < 10:
return 1
# Recursive: 1 + count of remaining digits
return 1 + count_digits(n // 10)
def count_even(lst):
"""Count even numbers"""
# Base case
if not lst:
return 0
# Count current if even
current = 1 if lst[0] % 2 == 0 else 0
return current + count_even(lst[1:])
# Test counting
numbers = [1, 2, 3, 2, 4, 2, 5]
print("List:", numbers)
print(f"Count of 2: {count_in_list(numbers, 2)}")
print(f"Count of 5: {count_in_list(numbers, 5)}")
print(f"Count of 9: {count_in_list(numbers, 9)}")
text = "recursion"
print(f"\nString: {text}")
print(f"Count 'r': {count_char(text, 'r')}")
print(f"Count 'i': {count_char(text, 'i')}")
print(f"\nDigits in 12345: {count_digits(12345)}")
print(f"Digits in 987: {count_digits(987)}")
print(f"\nEven numbers in {numbers}: {count_even(numbers)}")
numbers ← [1, 2, 3, 2, 4, 2, 5]
51# Test counting52numbers→ [1, 2, 3, 2, 4, 2, 5] = [1, 2, 3, 2, 4, 2, 5]5354print("List:", numbers[1, 2, 3, 2, 4, 2, 5])55print(f"Count of 2: {count_in_list(numbers[1, 2, 3, 2, 4, 2, 5], 2)}")56print(f"Count of 5: {count_in_list(numbers, 5)}")outputList: [1, 2, 3, 2, 4, 2, 5]current_count ← 0
pass 1 of 244def count_in_list(lst[1, 2, 3, 2, 4, 2, 5], target2):5 """Count value in list"""6 # Base case: empty list7 if not lst:8 return 0910 # Check first element11 current_count→ 0 = 1 if lst[0]1 == target2 else 01213 # Add count from rest14 return current_count0 + count_in_list(lst[1:][2, 3, 2, 4, 2, 5], target2)24 passes — pass 1 is the card above pass lsttargetlst[0]lst[1:]current_count1 [1, 2, 3, 2, 4, 2, 5] 2 1 [2, 3, 2, 4, 2, 5] 0 2 [2, 3, 2, 4, 2, 5] 2 2 [3, 2, 4, 2, 5] 1 3 [3, 2, 4, 2, 5] 2 3 [2, 4, 2, 5] 0 4 [2, 4, 2, 5] 2 2 [4, 2, 5] 1 5 [4, 2, 5] 2 4 [2, 5] 0 6 [2, 5] 2 2 [5] 1 7 [5] 2 5 [] 0 8 [] 2 — — — 9 [1, 2, 3, 2, 4, 2, 5] 5 1 [2, 3, 2, 4, 2, 5] 0 ⋯ 13 more passes ⋯ 23 [5] 9 5 [] 0 24 [] 9 — — — if not lst:
pass 1 of 36# Base case: empty list7if not lst[]:8 return 0print(f"Count of 2: {count_in_list(numbers, 2)}")
54print("List:", numbers)55print(f"Count of 2: {count_in_list(numbers[1, 2, 3, 2, 4, 2, 5], 2)}")56print(f"Count of 5: {count_in_list(numbers[1, 2, 3, 2, 4, 2, 5], 5)}")57print(f"Count of 9: {count_in_list(numbers, 9)}")outputCount of 2: 3print(f"Count of 5: {count_in_list(numbers, 5)}")
55print(f"Count of 2: {count_in_list(numbers, 2)}")56print(f"Count of 5: {count_in_list(numbers[1, 2, 3, 2, 4, 2, 5], 5)}")57print(f"Count of 9: {count_in_list(numbers[1, 2, 3, 2, 4, 2, 5], 9)}")outputCount of 5: 1text ← recursion
56print(f"Count of 5: {count_in_list(numbers, 5)}")57print(f"Count of 9: {count_in_list(numbers[1, 2, 3, 2, 4, 2, 5], 9)}")5859text→ recursion = "recursion"60print(f"\nString: {textrecursion}")61print(f"Count 'r': {count_char(textrecursion, 'r')}")62print(f"Count 'i': {count_char(text, 'i')}")outputCount of 9: 0 String: recursioncurrent_count ← 1
pass 1 of 2017def count_char(srecursion, targetr):18 """Count char in string"""19 # Base case: empty string20 if not s:21 return 02223 # Check first character24 current_count→ 1 = 1 if s[0]r == targetr else 02526 # Add count from rest27 return current_count1 + count_char(s[1:]ecursion, targetr)20 passes — pass 1 is the card above pass stargets[0]s[1:]current_count1 recursion r r ecursion 1 2 ecursion r e cursion 0 3 cursion r c ursion 0 4 ursion r u rsion 0 5 rsion r r sion 1 6 sion r s ion 0 7 ion r i on 0 8 on r o n 0 9 n r n (empty) 0 ⋯ 9 more passes ⋯ 19 n i n (empty) 0 20 (empty) i — — — if not s:
pass 1 of 219# Base case: empty string20if not s(empty):21 return 0print(f"Count 'r': {count_char(text, 'r')}")
60print(f"\nString: {text}")61print(f"Count 'r': {count_char(textrecursion, 'r')}")62print(f"Count 'i': {count_char(textrecursion, 'i')}")outputCount 'r': 2if not s:
pass 2 of 219# Base case: empty string20if not s(empty):21 return 0print(f"Count 'i': {count_char(text, 'i')}")
61print(f"Count 'r': {count_char(text, 'r')}")62print(f"Count 'i': {count_char(textrecursion, 'i')}")6364print(f"\nDigits in 12345: {count_digits(12345)}")65print(f"Digits in 987: {count_digits(987)}")outputCount 'i': 1def count_digits(n):
pass 1 of 830def count_digits(n12345):31 """Count digits in number"""32 # Base case: single digit33 if n < 10:34 return 13536 # Recursive: 1 + count of remaining digits37 return 1 + count_digits(n12345 // 10)All 8 passes — pass 1 is the card above pass n1 12345 2 1234 3 123 4 12 5 1 6 987 7 98 8 9 if n < 10:
pass 1 of 232# Base case: single digit33if n1 < 10:34 return 1print(f" Digits in 12345: {count_digits(12345)}")
64print(f"\nDigits in 12345: {count_digits(12345)}")65print(f"Digits in 987: {count_digits(987)}")output Digits in 12345: 5if n < 10:
pass 2 of 232# Base case: single digit33if n9 < 10:34 return 1print(f" Even numbers in {numbers}: {count_even(numbers)}")
64print(f"\nDigits in 12345: {count_digits(12345)}")65print(f"Digits in 987: {count_digits(987)}")6667print(f"\nEven numbers in {numbers[1, 2, 3, 2, 4, 2, 5]}: {count_even(numbers)}")outputDigits in 987: 3current ← 0
pass 1 of 840def count_even(lst[1, 2, 3, 2, 4, 2, 5]):41 """Count even numbers"""42 # Base case43 if not lst:44 return 04546 # Count current if even47 current→ 0 = 1 if lst[0]1 % 2 == 0 else 048 return current0 + count_even(lst[1:][2, 3, 2, 4, 2, 5])All 8 passes — pass 1 is the card above pass lstlst[0]lst[1:]current1 [1, 2, 3, 2, 4, 2, 5] 1 [2, 3, 2, 4, 2, 5] 0 2 [2, 3, 2, 4, 2, 5] 2 [3, 2, 4, 2, 5] 1 3 [3, 2, 4, 2, 5] 3 [2, 4, 2, 5] 0 4 [2, 4, 2, 5] 2 [4, 2, 5] 1 5 [4, 2, 5] 4 [2, 5] 1 6 [2, 5] 2 [5] 1 7 [5] 5 [] 0 8 [] — — — if not lst:
42# Base case43if not lst[]:44 return 0print(f" Even numbers in {numbers}: {count_even(numbers)}")
67print(f"\nEven numbers in {numbers[1, 2, 3, 2, 4, 2, 5]}: {count_even(numbers)}")output Even numbers in [1, 2, 3, 2, 4, 2, 5]: 4
Binary Search (Recursive)
binary_search.py
Replay: real traced execution (multi-file project)
# Recursive binary search
def binary_search(lst, target, left=0, right=None):
"""Recursive binary search"""
if right is None:
right = len(lst) - 1
# Base case: not found
if left > right:
return -1
# Find middle
mid = left + (right - left) // 2
# Check middle element
if lst[mid] == target:
return mid
# Recurse on appropriate half
if lst[mid] > target:
# Search left half
return binary_search(lst, target, left, mid - 1)
else:
# Search right half
return binary_search(lst, target, mid + 1, right)
def binary_search_trace(lst, target, left=0, right=None, depth=0):
"""Binary search with trace"""
if right is None:
right = len(lst) - 1
indent = " " * depth
# Base case
if left > right:
print(f"{indent}Not found")
return -1
# Find and check middle
mid = left + (right - left) // 2
print(f"{indent}Searching [{left}..{right}], mid={mid} (value={lst[mid]})")
if lst[mid] == target:
print(f"{indent}Found at index {mid}")
return mid
# Recurse
if lst[mid] > target:
print(f"{indent}Go left")
return binary_search_trace(lst, target, left, mid - 1, depth + 1)
else:
print(f"{indent}Go right")
return binary_search_trace(lst, target, mid + 1, right, depth + 1)
# Test binary search
numbers = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
print("List:", numbers)
print(f"Search 7: index {binary_search(numbers, 7)}")
print(f"Search 15: index {binary_search(numbers, 15)}")
print(f"Search 8: index {binary_search(numbers, 8)}")
print("\nSearch 13 with trace:")
binary_search_trace(numbers, 13)
numbers ← [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
58# Test binary search59numbers→ [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]6061print("List:", numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19])62print(f"Search 7: index {binary_search(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 7)}")63print(f"Search 15: index {binary_search(numbers, 15)}")outputList: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]def binary_search(lst, target, left=0, right=None):
pass 1 of 114def binary_search(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target7, left0=0, rightNone=NoneNone):5 """Recursive binary search"""6 if right is None:All 11 passes — pass 1 is the card above pass targetleftrightlst[mid]mid1 7 0 None — — 2 7 0 3 — 1 3 7 2 3 — 2 4 7 3 3 7 3 5 15 0 None — — 6 15 5 9 15 7 7 8 0 None — — 8 8 0 3 — 1 9 8 2 3 — 2 10 8 3 3 — 3 11 8 4 3 — — right ← 9
pass 1 of 35"""Recursive binary search"""6if rightNone is None:7 right→ 9 = len(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]) - 1All 3 passes — pass 1 is the card above pass right1 None → 9 2 None → 9 3 None → 9 mid ← 4
13# Find middle14mid→ 4 = left0 + (right9 - left) // 2if lst[mid] > target: # Search left half
pass 1 of 220# Recurse on appropriate half21if lst[mid]9 > target7:22 # Search left half23 return binary_search(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target7, left0, mid4 - 1)24else:else: # Search right half
pass 1 of 622 # Search left half23 return binary_search(lst, target, left, mid - 1)24else:25 # Search right half26 return binary_search(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target7, mid1 + 1, right3)All 6 passes — pass 1 is the card above pass targetmidrightlst[mid]left1 7 1 3 — — 2 7 2 3 7 — 3 15 4 9 15 — 4 8 1 3 — — 5 8 2 3 — — 6 8 3 3 — 4 if lst[mid] == target:
pass 1 of 216# Check middle element17if lst[mid]7 == target7:18 return mid3print(f"Search 7: index {binary_search(numbers, 7)}")
61print("List:", numbers)62print(f"Search 7: index {binary_search(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 7)}")63print(f"Search 15: index {binary_search(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 15)}")64print(f"Search 8: index {binary_search(numbers, 8)}")outputSearch 7: index 3mid ← 4
13# Find middle14mid→ 4 = left0 + (right9 - left) // 2if lst[mid] == target:
pass 2 of 216# Check middle element17if lst[mid]15 == target15:18 return mid7print(f"Search 15: index {binary_search(numbers, 15)}")
62print(f"Search 7: index {binary_search(numbers, 7)}")63print(f"Search 15: index {binary_search(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 15)}")64print(f"Search 8: index {binary_search(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 8)}")outputSearch 15: index 7mid ← 4
13# Find middle14mid→ 4 = left0 + (right9 - left) // 2if lst[mid] > target: # Search left half
pass 2 of 220# Recurse on appropriate half21if lst[mid]9 > target8:22 # Search left half23 return binary_search(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target8, left0, mid4 - 1)24else:if left > right:
9# Base case: not found10if left4 > right3:11 return -1print(f"Search 8: index {binary_search(numbers, 8)}")
63print(f"Search 15: index {binary_search(numbers, 15)}")64print(f"Search 8: index {binary_search(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 8)}")6566print("\nSearch 13 with trace:")67binary_search_trace(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 13)outputSearch 8: index -1 Search 13 with trace:def binary_search_trace(lst, target, left=0, right=None, depth=0):
pass 1 of 429def binary_search_trace(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target13, left0=0, rightNone=NoneNone, depth0=0):30 """Binary search with trace"""31 if right is None:All 4 passes — pass 1 is the card above pass leftdepthlst[mid]rightindentmid1 0 0 — None → 9 — — 2 5 1 15 9 7 3 5 2 11 6 5 4 6 3 13 6 6 right ← 9
30"""Binary search with trace"""31if rightNone is None:32 right→ 9 = len(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]) - 1indent ← (empty), mid ← 4
34indent→ (empty) = " " * depth03536# Base case37if left > right:38 print(f"{indent}Not found")39 return -14041# Find and check middle42mid→ 4 = left0 + (right9 - left) // 243print(f"{indent(empty)}Searching [{left0}..{right9}], mid={mid4} (value={lst[mid]9})")outputSearching [0..9], mid=4 (value=9)else:
pass 1 of 251 print(f"{indent}Go left")52 return binary_search_trace(lst, target, left, mid - 1, depth + 1)53else:54 print(f"{indent(empty)}Go right")55 return binary_search_trace(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target13, mid4 + 1, right9, depth0 + 1)outputGo rightif lst[mid] > target:
49# Recurse50if lst[mid]15 > target13:51 print(f"{indent }Go left")52 return binary_search_trace(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target13, left5, mid7 - 1, depth1 + 1)53else:output Go leftelse:
pass 2 of 251 print(f"{indent}Go left")52 return binary_search_trace(lst, target, left, mid - 1, depth + 1)53else:54 print(f"{indent }Go right")55 return binary_search_trace(lst[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], target13, mid5 + 1, right6, depth2 + 1)output Go rightif lst[mid] == target:
45if lst[mid]13 == target13:46 print(f"{indent }Found at index {mid6}")47 return mid6output Found at index 6binary_search_trace(numbers, 13)
66print("\nSearch 13 with trace:")67binary_search_trace(numbers[1, 3, 5, 7, 9, 11, 13, 15, 17, 19], 13)
Greatest Common Divisor
gcd.py
Replay: real traced execution (multi-file project)
# Greatest Common Divisor (GCD)
def gcd(a, b):
"""Euclidean algorithm"""
# Base case: b is 0
if b == 0:
return a
# Recursive case: gcd(b, a mod b)
return gcd(b, a % b)
def gcd_trace(a, b):
"""GCD with trace"""
print(f"gcd({a}, {b})")
# Base and recursive cases
if b == 0:
print(f" → {a}")
return a
return gcd_trace(b, a % b)
def lcm(a, b):
"""Least Common Multiple using GCD"""
return (a * b) // gcd(a, b)
def gcd_iterative(a, b):
"""Iterative GCD for comparison"""
while b != 0:
a, b = b, a % b
return a
# Test GCD
print(f"GCD(48, 18) = {gcd(48, 18)}")
print(f"GCD(100, 35) = {gcd(100, 35)}")
print(f"GCD(17, 13) = {gcd(17, 13)}")
print("\nGCD(48, 18) with trace:")
gcd_trace(48, 18)
print(f"\nLCM(12, 18) = {lcm(12, 18)}")
print(f"LCM(7, 5) = {lcm(7, 5)}")
print(f"\nIterative GCD(48, 18) = {gcd_iterative(48, 18)}")
print(f"GCD(48, 18) = {gcd(48, 18)}")
38# Test GCD39print(f"GCD(48, 18) = {gcd(48, 18)}")40print(f"GCD(100, 35) = {gcd(100, 35)}")def gcd(a, b):
pass 1 of 204def gcd(a48, b18):5 """Euclidean algorithm"""6 # Base case: b is 07 if b == 0:8 return a910 # Recursive case: gcd(b, a mod b)11 return gcd(b18, a48 % b)20 passes — pass 1 is the card above pass ab1 48 18 2 18 12 3 12 6 4 6 0 5 100 35 6 35 30 7 30 5 8 5 0 9 17 13 ⋯ 9 more passes ⋯ 19 2 1 20 1 0 if b == 0:
pass 1 of 56# Base case: b is 07if b0 == 0:8 return a6All 5 passes — pass 1 is the card above pass a1 6 2 5 3 1 4 6 5 1 print(f"GCD(48, 18) = {gcd(48, 18)}")
38# Test GCD39print(f"GCD(48, 18) = {gcd(48, 18)}")40print(f"GCD(100, 35) = {gcd(100, 35)}")41print(f"GCD(17, 13) = {gcd(17, 13)}")outputGCD(48, 18) = 6print(f"GCD(100, 35) = {gcd(100, 35)}")
39print(f"GCD(48, 18) = {gcd(48, 18)}")40print(f"GCD(100, 35) = {gcd(100, 35)}")41print(f"GCD(17, 13) = {gcd(17, 13)}")outputGCD(100, 35) = 5print(f"GCD(17, 13) = {gcd(17, 13)}")
40print(f"GCD(100, 35) = {gcd(100, 35)}")41print(f"GCD(17, 13) = {gcd(17, 13)}")4243print("\nGCD(48, 18) with trace:")44gcd_trace(48, 18)outputGCD(17, 13) = 1 GCD(48, 18) with trace:def gcd_trace(a, b):
pass 1 of 414def gcd_trace(a48, b18):15 """GCD with trace"""16 print(f"gcd({a48}, {b18})")1718 # Base and recursive cases19 if b == 0:20 print(f" → {a}")21 return a2223 return gcd_trace(b18, a48 % b)outputgcd(48, 18)All 4 passes — pass 1 is the card above pass ab1 48 18 2 18 12 3 12 6 4 6 0 if b == 0:
18# Base and recursive cases19if b0 == 0:20 print(f" → {a6}")21 return a6output → 6gcd_trace(48, 18)
43print("\nGCD(48, 18) with trace:")44gcd_trace(48, 18)4546print(f"\nLCM(12, 18) = {lcm(12, 18)}")47print(f"LCM(7, 5) = {lcm(7, 5)}")def lcm(a, b):
pass 1 of 226def lcm(a12, b18):27 """Least Common Multiple using GCD"""28 return (a12 * b18) // gcd(a, b)print(f" LCM(12, 18) = {lcm(12, 18)}")
46print(f"\nLCM(12, 18) = {lcm(12, 18)}")47print(f"LCM(7, 5) = {lcm(7, 5)}")output LCM(12, 18) = 36def lcm(a, b):
pass 2 of 226def lcm(a7, b5):27 """Least Common Multiple using GCD"""28 return (a7 * b5) // gcd(a, b)print(f"LCM(7, 5) = {lcm(7, 5)}")
46print(f"\nLCM(12, 18) = {lcm(12, 18)}")47print(f"LCM(7, 5) = {lcm(7, 5)}")4849print(f"\nIterative GCD(48, 18) = {gcd_iterative(48, 18)}")outputLCM(7, 5) = 35def gcd_iterative(a, b):
31def gcd_iterative(a48, b18):32 """Iterative GCD for comparison"""33 while b != 0:a ← 18, b ← 12
pass 1 of 332"""Iterative GCD for comparison"""33while b18 != 0:34 a→ 18, b→ 12 = b, a % b35return aAll 3 passes — pass 1 is the card above pass ab1 48 → 18 18 → 12 2 18 → 12 12 → 6 3 12 → 6 6 → 0 return a
34 a, b = b, a % b35return a6print(f" Iterative GCD(48, 18) = {gcd_iterative(48, 18)}")
49print(f"\nIterative GCD(48, 18) = {gcd_iterative(48, 18)}")output Iterative GCD(48, 18) = 6
euclidean_algorithm
GCD(a, b) = GCD(b, a mod b) until b is 0
Recursion Tips
- Start with base case: what is the simplest input?
- Ensure progress: each call moves toward base case
- Trust the recursion: assume it works for simpler case
- Combine results: decide how to use the recursive result
Exercise: practical.py
Implement recursive functions to flatten a nested list and find the maximum value in a list