8.0 KiB
Create Solutions
task: id: create-solutions name: Create Solutions description: Develop complete, tested solutions for all exercises with multiple approaches and explanations persona_default: exercise-creator inputs:
- chapter-exercises
- difficulty-level
- target-audience steps:
- Review all exercises in chapter
- Write complete tested solutions for each
- Include multiple solution approaches where applicable
- Add explanatory comments in solution code
- Document solution reasoning (why this approach)
- Test solutions thoroughly
- Create solution variations (beginner vs advanced)
- Add common mistake examples
- Estimate time to complete each exercise
- Format solutions for appendix or separate file
- Run execute-checklist.md with exercise-difficulty-checklist.md output: docs/solutions/chapter-{{n}}-solutions.md
Purpose
This task guides you through creating comprehensive, educational solutions for all chapter exercises. Good solutions teach readers how to approach problems, not just provide answers.
Workflow Steps
1. Review All Exercises
Catalog chapter exercises:
- List each exercise with its learning objective
- Note difficulty level (beginner/intermediate/advanced)
- Identify which concepts each exercise reinforces
- Check that exercises align with chapter content
2. Write Complete, Tested Solutions
Develop working solutions:
Solution Requirements:
- Code executes successfully
- Produces expected output
- Follows best practices from chapter
- Includes all necessary imports/setup
- Handles edge cases appropriately
Example Solution:
# Exercise 3.2: Implement a function to validate email addresses
import re
def validate_email(email):
"""
Validate email address format.
Args:
email (str): Email address to validate
Returns:
bool: True if valid, False otherwise
"""
# Pattern explanation:
# - ^[a-zA-Z0-9._%+-]+ : Username part (letters, numbers, special chars)
# - @ : Required @ symbol
# - [a-zA-Z0-9.-]+ : Domain name
# - \.[a-zA-Z]{2,}$ : Top-level domain (minimum 2 chars)
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
# Test cases
assert validate_email("user@example.com") == True
assert validate_email("invalid.email") == False
assert validate_email("user@domain.co.uk") == True
3. Include Multiple Approaches
Show alternative solutions:
Example - Multiple Approaches:
# Approach 1: Using regular expressions (recommended)
def validate_email_regex(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
# Approach 2: Using string methods (simpler but less robust)
def validate_email_simple(email):
return '@' in email and '.' in email.split('@')[-1]
# Approach 3: Using email library (most robust)
from email_validator import validate_email, EmailNotValidError
def validate_email_robust(email):
try:
validate_email(email)
return True
except EmailNotValidError:
return False
# Trade-offs:
# - Approach 1: Good balance of simplicity and accuracy
# - Approach 2: Too simple, accepts invalid emails
# - Approach 3: Most accurate, requires external library
4. Add Explanatory Comments
Explain the reasoning:
def fibonacci(n):
"""Generate Fibonacci sequence up to n terms."""
# We use an iterative approach rather than recursion
# because it's more efficient (O(n) vs O(2^n) time complexity)
# and avoids stack overflow for large n
if n <= 0:
return []
elif n == 1:
return [0]
# Initialize first two Fibonacci numbers
sequence = [0, 1]
# Generate remaining terms
# Each term is the sum of the previous two
for i in range(2, n):
next_term = sequence[i-1] + sequence[i-2]
sequence.append(next_term)
return sequence
5. Document Solution Reasoning
Explain why this approach:
Reasoning Template:
## Exercise 3.4 Solution
### Chosen Approach: Iterative Implementation
**Why this approach?**
- Time complexity: O(n) - efficient for large inputs
- Space complexity: O(n) - stores full sequence
- Avoids recursion depth limits
- Easy to understand and debug
**Alternative approaches considered:**
- Recursive: Simpler code but O(2^n) time complexity
- Generator: More memory-efficient but doesn't return list
- Matrix multiplication: Mathematically elegant but overkill
**When to use each:**
- Use iterative for most cases (good balance)
- Use generator when working with very large n
- Use recursive for teaching purposes only
6. Test Solutions Thoroughly
Validate correctness:
# Comprehensive test suite for solution
def test_fibonacci():
# Test edge cases
assert fibonacci(0) == []
assert fibonacci(1) == [0]
assert fibonacci(2) == [0, 1]
# Test normal cases
assert fibonacci(5) == [0, 1, 1, 2, 3]
assert fibonacci(10) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# Test correctness of sequence
result = fibonacci(20)
for i in range(2, len(result)):
assert result[i] == result[i-1] + result[i-2]
7. Create Solution Variations
Provide beginner and advanced versions:
Beginner Solution (verbose, educational):
def calculate_average(numbers):
"""Calculate the average of a list of numbers."""
# First, check if the list is empty to avoid division by zero
if len(numbers) == 0:
return 0
# Initialize a variable to store the sum
total = 0
# Add each number to the total
for number in numbers:
total = total + number
# Divide total by count to get average
count = len(numbers)
average = total / count
return average
Advanced Solution (concise, Pythonic):
def calculate_average(numbers):
"""Calculate the average of a list of numbers."""
return sum(numbers) / len(numbers) if numbers else 0
8. Add Common Mistakes
Show what to avoid:
## Common Mistakes
### ❌ Mistake 1: Not handling empty input
```python
def calculate_average(numbers):
return sum(numbers) / len(numbers) # ZeroDivisionError if empty!
Problem: Crashes on empty list.
Fix: Check for empty input first.
❌ Mistake 2: Modifying input during iteration
def remove_negatives(numbers):
for num in numbers:
if num < 0:
numbers.remove(num) # Skips elements!
return numbers
Problem: Modifying list while iterating causes skipped elements.
Fix: Create new list or iterate backwards.
### 9. Estimate Completion Time
Help readers pace themselves:
```markdown
## Exercise Time Estimates
| Exercise | Difficulty | Estimated Time |
|----------|-----------|----------------|
| 3.1 | Beginner | 10-15 minutes |
| 3.2 | Intermediate | 20-30 minutes |
| 3.3 | Advanced | 45-60 minutes |
| 3.4 | Challenge | 1-2 hours |
10. Format for Appendix
Structure solutions document:
Template:
# Chapter 3 Solutions
## Exercise 3.1: [Exercise Title]
**Difficulty:** Beginner
**Estimated Time:** 10-15 minutes
### Solution
```python
[solution code]
Explanation
[Detailed explanation of approach]
Alternative Approaches
[Other valid solutions]
Common Mistakes
[What to avoid]
Exercise 3.2: [Next Exercise]
[Same structure]
## Success Criteria
- [ ] All exercises have complete solutions
- [ ] Solutions are tested and work correctly
- [ ] Multiple approaches shown where applicable
- [ ] Explanatory comments included
- [ ] Solution reasoning documented
- [ ] Beginner and advanced variations provided
- [ ] Common mistakes identified
- [ ] Time estimates provided
- [ ] Formatted for appendix or separate file
- [ ] Exercise difficulty checklist passed
## Next Steps
1. Include solutions in book appendix or companion website
2. Consider providing partial solutions for harder exercises
3. Create solution videos for complex exercises (optional)
4. Test solutions with beta readers