# Problem 3: Mastering FizzBuzz in Python: A Step-by-Step Guide

FizzBuzz is one of the most famous coding interview questions. While it may seem simple at first glance, it tests a programmer's ability to handle conditional logic, control flow, and edge cases effectively. In this post, we'll break down a clean and efficient Python solution.

## **The Problem**

The rules of FizzBuzz are straightforward. We need to write a function that prints numbers from 1 to `n`, but with specific substitutions:

* For multiples of **3**, print "Fizz".
    
* For multiples of **5**, print "Buzz".
    
* For multiples of **both 3 and 5**, print "FizzBuzz".
    
* For all other numbers, print the number itself.
    

The function should return a list of these results.

**Example:** `fizzbuzz(15)` should return: `[1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz']`

---

## **The Solution**

Here is a clear and readable Python implementation:

```python
def fizzbuzz(n):
    """
    Generates the FizzBuzz sequence up to n.
    """
    results = []

    # Loop from 1 to n (inclusive)
    for i in range(1, n + 1):
        # Check for multiples of both 3 and 5 (15) first
        if i % 3 == 0 and i % 5 == 0:
            results.append("FizzBuzz")
        else:
            # Check for multiples of 3
            if i % 3 == 0:
                results.append("Fizz")
            # Check for multiples of 5
            elif i % 5 == 0:
                results.append("Buzz")
            # Otherwise, add the number itself
            else:
                results.append(i)

    return results

# Example usage
print(fizzbuzz(15))
```

---

## **Code Breakdown**

Let's analyze the solution line by line to understand exactly how it works.

### **1\. Function Definition and Initialization**

```python
def fizzbuzz(n):
    results = []
```

We define a function `fizzbuzz` that accepts an integer `n` as the upper limit. We also initialize an empty list `results` to store our output.

### **2\. The Loop**

```python
for i in range(1, n + 1):
```

We use `range(1, n + 1)` to generate numbers starting from 1 up to `n`. The `+ 1` is crucial because the `range` function in Python is exclusive at the upper bound.

### **3\. The "FizzBuzz" Condition**

```python
if i % 3 == 0 and i % 5 == 0:
    results.append("FizzBuzz")
```

**This is the most critical part.** We must check if a number is divisible by **both** 3 and 5 (which means it's a multiple of 15) *before* checking for 3 or 5 individually. If we checked for 3 first, the number 15 would be labeled "Fizz" instead of "FizzBuzz", which would be incorrect.

### **4\. The "Fizz" and "Buzz" Conditions**

```python
else:
    if i % 3 == 0:
        results.append("Fizz")
    elif i % 5 == 0:
        results.append("Buzz")
```

If the number isn't a multiple of 15, we proceed to check:

* `i % 3 == 0`: If true, append "Fizz".
    
* `i % 5 == 0`: If true, append "Buzz".
    

Using `elif` ensures that these conditions are mutually exclusive within the `else` block of the main condition.

### **5\. The Default Case**

```python
else:
    results.append(i)
```

If none of the above conditions are met (the number isn't divisible by 3 or 5), we simply append the number `i` to the list.

---

## **Key Takeaways**

1. **Order Matters**: The condition for "FizzBuzz" (divisible by 15) must come before the checks for "Fizz" (3) or "Buzz" (5).
    
2. **Modulo Operator**: The `%` operator is your best friend for checking divisibility. `i % n == 0` means `i` is perfectly divisible by `n`.
    
3. **Complexity**:
    
    * **Time Complexity**: **O(n)**, because we iterate through the numbers exactly once.
        
    * **Space Complexity**: **O(n)**, because we store a result for every number up to `n`.
        

Mastering this logic is a great first step in understanding control flow and algorithmic thinking!
