python

solutions

solutions.py🐍
"""
Solutions for Module 05 - Functions Exercises

These are reference solutions. Try to solve the exercises yourself first!
"""

# =============================================================================
# Basic Function Solutions
# =============================================================================

def greet(name: str) -> str:
    """Return a greeting message."""
    return f"Hello, {name}!"


def add_numbers(a: float, b: float) -> float:
    """Add two numbers and return the result."""
    return a + b


def is_even(number: int) -> bool:
    """Check if a number is even."""
    return number % 2 == 0


def factorial(n: int) -> int:
    """Calculate factorial of n (recursive)."""
    if n <= 1:
        return 1
    return n * factorial(n - 1)


def factorial_iterative(n: int) -> int:
    """Calculate factorial of n (iterative)."""
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result


# =============================================================================
# Default Arguments & Keyword Arguments
# =============================================================================

def power(base: float, exponent: float = 2) -> float:
    """Calculate base raised to exponent (default: square)."""
    return base ** exponent


def create_user(name: str, age: int = 0, email: str = "", active: bool = True) -> dict:
    """Create a user dictionary with default values."""
    return {
        "name": name,
        "age": age,
        "email": email,
        "active": active
    }


def format_name(first: str, last: str, *, middle: str = "", title: str = "") -> str:
    """Format a full name with optional middle name and title."""
    parts = []
    if title:
        parts.append(title)
    parts.append(first)
    if middle:
        parts.append(middle)
    parts.append(last)
    return " ".join(parts)


# =============================================================================
# *args and **kwargs
# =============================================================================

def sum_all(*args: float) -> float:
    """Sum all provided numbers."""
    return sum(args)


def average(*args: float) -> float:
    """Calculate average of all provided numbers."""
    if not args:
        return 0.0
    return sum(args) / len(args)


def build_profile(name: str, **kwargs) -> dict:
    """Build a user profile from name and any additional attributes."""
    profile = {"name": name}
    profile.update(kwargs)
    return profile


def call_with_logging(func, *args, **kwargs):
    """Call a function and log the call."""
    print(f"Calling {func.__name__} with args={args}, kwargs={kwargs}")
    result = func(*args, **kwargs)
    print(f"Result: {result}")
    return result


# =============================================================================
# Lambda Functions
# =============================================================================

# Sort by second element
pairs = [(1, 'b'), (2, 'a'), (3, 'c')]
sorted_pairs = sorted(pairs, key=lambda x: x[1])

# Filter even numbers
numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))

# Map to squares
squares = list(map(lambda x: x**2, numbers))

# Sort strings by length
words = ["apple", "pie", "banana", "kiwi"]
by_length = sorted(words, key=lambda x: len(x))


# =============================================================================
# Higher-Order Functions
# =============================================================================

def apply_operation(numbers: list, operation) -> list:
    """Apply an operation to each number in the list."""
    return [operation(n) for n in numbers]


def create_multiplier(factor: int):
    """Return a function that multiplies by factor (closure)."""
    def multiplier(x):
        return x * factor
    return multiplier


def compose(f, g):
    """Return a function that composes f and g: f(g(x))."""
    def composed(x):
        return f(g(x))
    return composed


def retry(max_attempts: int = 3):
    """Decorator that retries a function on exception."""
    def decorator(func):
        def wrapper(*args, **kwargs):
            last_error = None
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    last_error = e
                    print(f"Attempt {attempt + 1} failed: {e}")
            raise last_error
        return wrapper
    return decorator


# =============================================================================
# Recursive Functions
# =============================================================================

def fibonacci(n: int) -> int:
    """Calculate nth Fibonacci number (recursive)."""
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)


def fibonacci_memo(n: int, memo: dict = None) -> int:
    """Calculate nth Fibonacci number with memoization."""
    if memo is None:
        memo = {}
    if n in memo:
        return memo[n]
    if n <= 1:
        return n
    memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
    return memo[n]


def flatten(nested_list: list) -> list:
    """Flatten a nested list recursively."""
    result = []
    for item in nested_list:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result


def deep_sum(data) -> float:
    """Sum all numbers in a nested structure."""
    if isinstance(data, (int, float)):
        return data
    elif isinstance(data, (list, tuple)):
        return sum(deep_sum(item) for item in data)
    elif isinstance(data, dict):
        return sum(deep_sum(v) for v in data.values())
    return 0


# =============================================================================
# Test Solutions
# =============================================================================

if __name__ == "__main__":
    # Test basic functions
    assert greet("Alice") == "Hello, Alice!"
    assert add_numbers(2, 3) == 5
    assert is_even(4) == True
    assert factorial(5) == 120
    
    # Test default arguments
    assert power(3) == 9
    assert power(2, 3) == 8
    user = create_user("Bob")
    assert user["name"] == "Bob"
    assert user["active"] == True
    
    # Test *args and **kwargs
    assert sum_all(1, 2, 3, 4) == 10
    assert average(10, 20, 30) == 20.0
    profile = build_profile("Alice", age=30, city="NYC")
    assert profile["city"] == "NYC"
    
    # Test closures
    double = create_multiplier(2)
    triple = create_multiplier(3)
    assert double(5) == 10
    assert triple(5) == 15
    
    # Test recursive functions
    assert fibonacci(10) == 55
    assert flatten([1, [2, 3], [4, [5, 6]]]) == [1, 2, 3, 4, 5, 6]
    assert deep_sum([1, [2, 3], {"a": 4}]) == 10
    
    print("All solutions verified! ✓")
Solutions - Python Tutorial | DeepML