FizzBuzz Understanding

I want to understand why does the order matters, look at my code first and then look at the solution.

#include <iostream> using namespace std; int main() { for (int i; i <= 100; i++) { if (i % 3 == 0) { cout << "Fizz\n"; } else if (i % 5 == 0) { cout << "Buzz\n"; } else if (i % 15 == 0) { cout << "FizzBuzz"; } else { cout << i << "\n"; } } return 0; }

Solution

#include <iostream> int main() { for (int i = 1; i <= 100; i++) { if (i % 15 == 0) { std::cout << "FizzBuzz\n"; } else if (i % 5 == 0) { std::cout << "Buzz\n"; } else if (i % 3 == 0) { std::cout << "Fizz\n"; } else { std::cout << i << "\n"; } } return 0; }

Line 12 in the first example will have no effect since the two important cases are both failed.

Consider, if we get to this conditional we must have failed the two ahead of it. Since both 3 and 5 are eliminated then the number can’t possibly be their LCM.

We want to rule out the LCM and its multiples before singling out 3 and 5.

1 Like

Note that if something is divisible by 15, then it is divisible by 5 and it is divisible by 3
(since 15 is a common multiple of 5 and 3). [Looking at it another way, 5 and 3 are factors of 15.]

So any i that gives true for the condition (i % 15 == 0)
would also give true for (i % 5 == 0) and true for (i % 3 == 0)

Doing (i % 15 == 0) first is necessary because …

If you do if(i % 3 == 0) before having else if (i % 15 == 0),
and you happen to be dealing with an i that is divisible by 15 (meaning that (i % 15 == 0) is true),
then (i % 3 == 0) would be true,
so that if-block would be executed,
but the else-if blocks afterward would not be executed
(since else-if blocks are skipped when the if-block before them runs).

So the else-if block with condition (i % 15 == 0) never gets to run,
so "FizzBuzz" never gets printed to the screen / console.

1 Like

Extra Study

Where we can reverse the order is if we are building an array.

The first step would be to populate the array of length N, with a range from 1 to N, both inclusive.

The next step would be to cycle the array in steps of 3, beginning on the index where the value 3 is stored. Each index would be assigned the value, "Fizz".

The next step would be to cycle the array in steps of 5, beginning on the index where the value 5 is stored. Each index would be assigned the value, “Buzz”.

Now we bring in the LCM (Least Common Multiple) as the final step, beginning at the index where the 15 was initially. It will currently have the value, "Buzz" from the last pass on 5 and multiples of 5. In steps of 15 each index will be given the value, "FizzBuzz".

The final array will now be fully configured. An array with at least 105 elements can be queried, thus,

fizzbuzz[105]    //  FizzBuzz

fizzbuzz[100]    //  Buzz

fizzbuzz[102]    //  Fizz

So there is a situation where the LCM is last rather than first. Logic and coding is like that. Where an approach may be incorrect in one situation, it can be correct in another scenario. Keep an open mind and make note of these differences when you observe them.

3 Likes