Why Recursion Exists and What Loops Cannot Express Cleanly
📖 Scenario: Imagine you have a set of nested boxes, each box inside another. You want to find the smallest box inside all the boxes. This is like a problem where you need to look inside each box one by one, but some boxes contain other boxes inside them. Loops can help you repeat actions, but they struggle when the number of boxes inside boxes is unknown or changes. Recursion helps by letting a function call itself to handle each smaller box until it finds the smallest one.
🎯 Goal: You will build a simple Rust program that uses recursion to find the smallest number in a nested list of numbers. This shows why recursion is useful when loops cannot easily handle nested or unknown levels of data.
📋 What You'll Learn
Create a nested vector of integers representing boxes inside boxes
Create a helper variable to track the smallest number found
Write a recursive function to find the smallest number in the nested vector
Print the smallest number found
💡 Why This Matters
🌍 Real World
Recursion is used in file system searches, parsing nested data like JSON or XML, and solving problems with hierarchical data such as organization charts or family trees.
💼 Career
Understanding recursion is essential for software developers working with complex data structures, algorithms, and tasks that involve nested or hierarchical information.
Progress0 / 4 steps
1
Create a nested vector of integers
Create a variable called nested_numbers that holds a vector with these exact elements: vec![1, 2, vec![3, 4], 5]. Use Vec where NestedNumber is an enum you define with variants Int(i32) and List(Vec).
DSA Rust
Hint
Define an enum called NestedNumber with two variants: Int(i32) for single numbers and List(Vec) for nested lists. Then create nested_numbers as a vector of these enum values.
2
Create a variable to track the smallest number
Inside main, create a mutable variable called smallest and set it to i32::MAX to start with the largest possible integer.
DSA Rust
Hint
Use let mut smallest = i32::MAX; to start with the largest integer so you can find smaller numbers later.
3
Write a recursive function to find the smallest number
Write a function called find_smallest that takes a reference to a Vec and a mutable reference to smallest: &mut i32. It should loop over each NestedNumber in the vector. If it is Int(value), update smallest if value is smaller. If it is List(inner_vec), call find_smallest recursively on inner_vec. Call this function from main with nested_numbers and &mut smallest.
DSA Rust
Hint
Use a for loop and match to check each item. If it is an integer, compare and update smallest. If it is a list, call find_smallest recursively.
4
Print the smallest number found
Add a println! statement in main to print the text "Smallest number is: {}" with the value of smallest.
DSA Rust
Hint
Use println!("Smallest number is: {}", smallest); to show the result.
Practice
(1/5)
1. Why do we use recursion instead of loops in some problems? fn factorial(n: u32) -> u32 { if n == 0 { 1 } else { n * factorial(n - 1) } }
easy
A. Recursion uses less memory than loops.
B. Loops are always slower than recursion.
C. Recursion can express problems with self-similar structure more naturally.
D. Loops cannot perform repeated actions.
Solution
Step 1: Understand recursion's purpose
Recursion is useful when a problem can be broken down into smaller similar problems, like factorial.
Step 2: Compare recursion and loops
Loops repeat actions but do not naturally express self-similar or nested problems as clearly as recursion.
Final Answer:
Recursion can express problems with self-similar structure more naturally. -> Option C
Quick Check:
Recursion = natural for self-similar problems [OK]
Hint: Recursion fits problems breaking into smaller similar parts [OK]
Common Mistakes:
Thinking loops are always slower
Believing recursion uses less memory
Assuming loops cannot repeat actions
2. Which of the following is the correct Rust syntax for a recursive function that sums numbers from 1 to n?
easy
A. fn sum(n: u32) -> u32 { if n == 0 { 0 } else { n + sum(n - 1) } }
B. fn sum(n: u32) -> u32 { loop { n + sum(n - 1) } }
C. fn sum(n: u32) -> u32 { while n > 0 { n + sum(n - 1) } }
D. fn sum(n: u32) -> u32 { if n == 0 { 1 } else { n * sum(n - 1) } }
Solution
Step 1: Identify correct base case and recursion
fn sum(n: u32) -> u32 { if n == 0 { 0 } else { n + sum(n - 1) } } correctly returns 0 when n is 0 and sums recursively.
Step 2: Check syntax and logic
Options B and C misuse loops inside recursion, causing infinite loops or errors. fn sum(n: u32) -> u32 { if n == 0 { 1 } else { n * sum(n - 1) } } multiplies instead of sums.
Final Answer:
fn sum(n: u32) -> u32 { if n == 0 { 0 } else { n + sum(n - 1) } } -> Option A
Quick Check:
Correct recursion syntax = fn sum(n: u32) -> u32 { if n == 0 { 0 } else { n + sum(n - 1) } } [OK]
Hint: Look for correct base case and recursive call pattern [OK]