Start learning free

LESSON 162 OF 348 · LOOPS - CHALLENGES

Fizz Buzz in Kotlin: A Loop with Modulo Checks

Practice O(n) Homework Read the full explanation

Given a positive integer n print each number from 1 to n, each on a new line.
For each multiple of 3, print "Fizz" instead of the number.
For each multiple of 5, print "Buzz" instead of the number.
For numbers which are multiples of both 3 and 5, print "FizzBuzz" instead of the number.

Example:

Input: n = 15
Output:
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

Note:

Your algorithm should run in O(n) time and use O(1) space.


Hints:

In order to print the items, we should iterate through the numbers 1 to n and check for each of them what condition is satisfied to print accordingly. How can we do this?

Let's use a for loop and a variable i to iterate through the numbers 1 to n:
for each i : 1 -> n:
	# Print either i or "Fizz" or "Buzz" or "FizzBuzz"
Inside the loop, we need to decide what should be printed between Fizz, Buzz, FizzBuzz and i.
How can we do this?

Using sequential if - else statements along with the modulo (%) operator:
for each i : 1 -> n:
	if i % 15 == 0:
    		print("FizzBuzz")
  	else if i % 3 == 0:
    		print("Fizz")
  	else if i % 5 == 0:
    		print("Buzz")
  	else:
    		print(i)

We have a for loop that performs exactly n iterations, thus the Time Complexity is O(n).
The only extra space we use is the iterator variable i inside the loop, thus the Extra Space used is O(1).

Video Solution:

SOLVE IT YOURSELF
Ctrl + Enter to check

KOTLIN · LOOPS - CHALLENGES

Fizz Buzz in Kotlin, explained

Problem overview

The function fizzBuzz(n: Int) prints the numbers from 1 to n, one per line, with three replacements. A multiple of 3 prints Fizz instead of the number, a multiple of 5 prints Buzz, and a number that is a multiple of both prints FizzBuzz.

For n = 15 the output is 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz. The statement asks for O(n) time and O(1) space.

Approach

Visit each number once with a for loop and decide what to print for it. The decision uses the remainder operator %: i % 3 == 0 means i is a multiple of 3.

The order of the checks matters. A number such as 15 is a multiple of 3 and of 5, and it must print FizzBuzz, not Fizz. So the case for both has to be tested first. A number is a multiple of both 3 and 5 exactly when it is a multiple of 15, so one check, i % 15 == 0, covers it.

Step by step

  1. Loop from 1 to n. The range 1..n includes both ends, so the loop reaches n itself.
  2. Test multiples of 15 first. If i % 15 == 0, print FizzBuzz.
  3. Then test multiples of 3. In the else if, a number that gets here is not a multiple of 15, so printing Fizz is right.
  4. Then test multiples of 5 the same way and print Buzz.
  5. Otherwise print the number itself in the final else.

Exactly one branch runs per number, because each else is reached only when the earlier conditions were false.

Tracing three numbers

Follow the checks for 9, 10 and 15 to see how the chain behaves:

  • 9: 9 % 15 is 9, not 0, so the first test fails. 9 % 3 is 0, so the loop prints Fizz and skips the remaining tests.
  • 10: 10 % 15 is 10 and 10 % 3 is 1, so both tests fail. 10 % 5 is 0, so it prints Buzz.
  • 15: 15 % 15 is 0, so it prints FizzBuzz immediately, and the checks for 3 and 5 are never reached.

Another way to write the test

Instead of testing 15, the first condition could test both factors: i % 3 == 0 && i % 5 == 0. It gives the same answers, because a number divisible by 3 and by 5 is divisible by 15 (3 and 5 share no factor). The i % 15 form is shorter and does one remainder operation instead of two. Both are O(1) per number. A different idea is to build the word in pieces, adding Fizz when divisible by 3 and Buzz when divisible by 5, and printing the number only if the word is still empty. The lesson uses the plain chain because it is the easiest to read.

The solution in Kotlin

class Solution {
    fun fizzBuzz(n: Int) {
        for (i in 1..n) {
            if (i % 15 == 0) {
                println("FizzBuzz")
            } else if (i % 3 == 0) {
                println("Fizz")
            } else if (i % 5 == 0) {
                println("Buzz")
            } else {
                println(i)
            }
        }
    }
}

Kotlin details:

  • Ranges. 1..n is inclusive on both ends. If you wrote 1 until n, the loop would stop at n - 1 and miss the last line. For n = 0 the range is empty and the loop doesn't run.
  • The loop variable. i is declared by the for itself and is read-only inside the body, so you can't assign to it.
  • println takes any value. It prints a string or an Int the same way, so the last branch needs no conversion.
  • Remainder. % on non-negative Int values gives what is left after division, so 9 % 3 is 0 and 10 % 3 is 1.

The same logic with when

Kotlin's when without an argument checks its conditions from top to bottom and runs the first branch that is true, which is the same behaviour as the else if chain:

when {
    i % 15 == 0 -> println("FizzBuzz")
    i % 3 == 0 -> println("Fizz")
    i % 5 == 0 -> println("Buzz")
    else -> println(i)
}

Placed inside the loop, it prints the same 15 lines for n = 15. The order rule is unchanged: the 15 branch must come first.

Complexity

Time: O(n). The loop makes exactly n passes and does a constant amount of work in each.

Space: O(1). The only variable is the loop counter. Nothing is stored, because each line is printed as soon as it is decided.

Edge cases and common mistakes

  • Checking 3 before 15. Then 15 prints Fizz, because the first matching branch wins and the FizzBuzz branch is never reached. The both-case must come first.
  • Using separate if statements. With independent if statements, 15 would print Fizz and Buzz on two separate lines, and the plain-number case would need its own guard to stay silent. The else if chain makes the cases exclusive.
  • Printing the wrong text. The words are case-sensitive: fizzbuzz or Fizzbuzz won't match FizzBuzz.
  • Starting at 0. Zero is a multiple of every number, so a loop from 0 would print FizzBuzz first.
  • Stopping short. 1 until n or i < n misses n.
  • Using = instead of ==. A comparison needs ==. In Kotlin, assignment is not an expression, so if (i % 3 = 0) doesn't compile.

Testing

  • n = 1 prints 1.
  • n = 3 prints 1, 2, Fizz.
  • n = 5 prints 1, 2, Fizz, 4, Buzz.
  • n = 15 ends with FizzBuzz.
  • n = 30 ends with Buzz on line 25, Fizz on line 27 and FizzBuzz on line 30.
Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
Start learning free