FizzBuzz is a children's counting game commonly used to teach division. It also happens to be a very common coding interview problem, because it's a great test of several basic programming patterns. If you're going for your first Python interview, it's really important that you understand how to solve a problem like this.

The Rules of the Game

Generally FizzBuzz is played in a group, where players take it in turns to say the next number in a sequence, counting one at a time. If the number is divisible by three, the player must say, "Fizz" instead of the number itself; if the number is divisible by five, the player must say, "Buzz"; and if the number is divisible by three and five, the player has to say, "Fizz buzz".

The first 10 iterations therefore look like this:

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz

Usually getting the answer wrong causes the elimination of the player, and the game continues until only one person remains.

Putting the Game into Code

A common request in coding interviews might be to print the first 100 items of FizzBuzz. The solution itself is quite simple, and requires very basic tools, but there are a number of places people slip up.

One thing we know for certain is that we're going to need some kind of a loop, since we need to perform a given action numerous times. It doesn't strictly matter if we opt for a for loop or a while loop here, but perhaps a for loop is more appropriate, since we want to perform a specific number of iterations. We're going to use range() to generate the list of numbers for us to iterate over in this case.

For now we'll forget about the body of the loop, writing pass to indicate that it is intentionally empty.

for number in range(1, 101):
    pass

There are two things to be keep in mind when constructing our loop:

  1. In programming, we usually start counting from zero, but in normal life we usually start counting from one. We need to make sure our loop starts at one, and not zero, unless the interviewer says otherwise.
  2. The limit we provide to range() is not inclusive. It's not enough for us to use range(1, 100) as the 100 will not show up in our output.

The Loop Logic

Now that we have our for loop set up, we need to decide how we're going to properly handle the replacement of certain numbers with the appropriate words.

Probably the easiest way to tackle this is to perform a series of divisions on a given number to find out its factors. Python has a handy operator called modulo % which (for positive numbers) returns the remainder portion of a Euclidean division. Modulo's counterpart, //, returns the quotient. You can read more about these operators in our post on this topic.

If a number is divisible by three, the result of our modulo operation should be 0, so we can now write a simple if condition.

if number % 3 == 0:
    pass

If you prefer, you can make use of standard division and the is_integer() method instead:

if (number / 3).is_integer():
    pass

Checking for FizzBuzz can be done in a number of ways. We can use and to check a number is both divisible by 3 and 5, or you might realise that any number divisible by both 3 and 5 is divisible by 15:

if number % 3 == 0 and number % 5 == 0:
    print("FizzBuzz")

if number % 15 == 0:
    print("FizzBuzz")

Avoiding Common Mistakes

So far so good, but it's easy to fall into a number of other traps if we're not careful. One problem I see a lot among our students is something like this:

for number in range(1, 101):
    if number % 3 == 0:
        print("Fizz")
    if number % 5 == 0:
        print("Buzz")
    if number % 15 == 0:
        print("FizzBuzz")
    if number % 3 != 0 and number % 5 !=0:
        print(number)

There are actually a few problems here. The first is that we get an undesirable output for the 15th iteration:

...
13
14
Fizz
Buzz
FizzBuzz

We triggered all of the if conditions, because we forget to tie these conditions together into a single block. We should be using elif to ensure that only one condition ever triggers. Similarly, there's no need for us to perform that final check for numbers which don't meet any of our special conditions. We can just use else.

for number in range(1, 101):
    if number % 3 == 0:
        print("Fizz")
    elif number % 5 == 0:
        print("Buzz")
    elif number % 15 == 0:
        print("FizzBuzz")
    else:
        print(number)

That solved some of our problems, and made our code a bit neater, but now we have a new problem:

...
13
14
Fizz

We never trigger "FizzBuzz", because any number which satisfies "FizzBuzz" also satisfies our first condition for "Fizz". This is an incredibly common error I see our students making, not just for this specific problem.

We have to ensure that our "FizzBuzz" condition comes first, guaranteeing that we don't accidentally trigger the "Fizz" or "Buzz" conditions too early.

for number in range(1, 101):
    if number % 15 == 0:
        print("FizzBuzz")
    elif number % 3 == 0:
        print("Fizz")
    elif number % 5 == 0:
        print("Buzz")
    else:
        print(number)

Now everything works as expected, and running our program will give us the first 100 results for FizzBuzz. Awesome!

Alternative Solutions

As with all things in programming, there's more than one way to solve this problem, so I'm going to show off a couple of other solutions here. If you have a different way of solving the problem, we'd love to hear about it over on Twitter.

Nested if Statements

One way you could tackle the logic inside the for loop is to put conditional blocks inside other conditional blocks. We can test anything divisible by 3 to see if it's also divisible by 5, helping us avoid the ordering issue we saw earlier that prevents "FizzBuzz" printing to the console.

for number in range(1, 101):
    if number % 3 == 0:
        if number % 5 == 0:
            print("FizzBuzz")
        else:
            print("Fizz")
    elif number % 5 == 0:
        print("Buzz")
    else:
        print(number)

String Concatenation

A completely different type of solution involves appending "Fizz" and "Buzz" to an empty string depending on certain conditions.

We start each iteration with an empty string, and append "Fizz" should the number be divisible by 3, and append "Buzz" should the number be divisible by 5. Note that these are independent if statement, so both always run. This means that in the event of "FizzBuzz", both "Fizz" and "Buzz" get appended to the string, requiring no additional checks.

Once the string has been prepared, we can check if it's still empty, printing the number if so:

for number in range(1, 101):
    string = ""

    if number % 3 == 0:
        string += "Fizz"
    if number % 5 == 0:
        string += "Buzz"
    
    if string == "":
        print(number)
    else:
        print(string)

This final check for the empty string can be made shorter by exploiting Python's or operator, which always returns one of the operands, rather than True or False. We talk about that more in another post.

for number in range(1, 101):
    string = ""

    if number % 3 == 0:
        string += "Fizz"
    if number % 5 == 0:
        string += "Buzz"
    
    print(string or number)

Ternary String Concatenation

This solution is much like the solution above, but uses Python's slightly obscure ternary operator syntax to perform the string concatenation.

for number in range(1, 101):
    string = "Fizz" if number % 3 == 0 else ""
    string += "Buzz" if number % 5 == 0 else ""
    
    if string == "":
        print(number)
    else:
        print(string)

We can use the same trick with or here as well.

for number in range(1, 101):
    string = "Fizz" if number % 3 == 0 else ""
    string += "Buzz" if number % 5 == 0 else ""
    
    print(string or number)

Wrapping Up

FizzBuzz is a fun challenge, and ideal for newer programmers. I hope you found this little walk through helpful, and we'd love to see your own solutions to this problem.

If you're just starting out with programming, be sure to follow us on Twitter to keep up to date with all our content, and maybe consider checking out our Complete Python Course, or joining our Discord server. We'd love to have you!

You can also sign up to our mailing list below. We regularly post discount codes for our subscribers, so it's a great way to ensure you're always getting the best deal available on our courses.