BMAD-METHOD/expansion-packs/bmad-technical-writing/tasks/create-solutions.md

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