FizzBuzz
FizzBuzz is a counting game: go from 1 to 100, but say "Fizz" instead of every multiple of 3, "Buzz" instead of every multiple of 5, and "FizzBuzz" instead of every multiple of both. It began as a children's game for practising division and became the most famous little test in programming — not because it is hard, but because it is so easy to get almost right.
The program needs only Parts 1–3. It also keeps a tally of each kind of answer, which turns out to be a handy way of checking that the logic is right.
How it is put together
Everything happens inside one for loop. Each pass asks a chain of questions about n, prints one answer, counts it, and then decides what goes after it — a space or a line break:
flowchart LR
n(["n from 1 to 100"]) --> q15{"n % 15 == 0?"}
q15 -- "yes" --> fb["FizzBuzz"]
q15 -- "no" --> q3{"n % 3 == 0?"}
q3 -- "yes" --> f["Fizz"]
q3 -- "no" --> q5{"n % 5 == 0?"}
q5 -- "yes" --> b["Buzz"]
q5 -- "no" --> num["the number"]| Piece | Lessons it uses |
|---|---|
n % 3 == 0 | Arithmetic (%), Comparison |
| The chain of questions | Else if |
| Walking 1 to 100 | For, Range |
| The tallies | Mutable, Assignment (+=) |
| Ten answers to each line | If, Console (Print and PrintLine) |
"Divides exactly" is a remainder of zero
% gives the remainder of a division. When a number divides by 3 exactly, nothing is left over, so n % 3 == 0 reads as "n is a multiple of 3". A number that is a multiple of both 3 and 5 is a multiple of 15, so one test covers "both":
if n % 15 == 0 {
Print("FizzBuzz");
fizzBuzzes += 1;
} else if n % 3 == 0 {
Print("Fizz");
fizzes += 1;
} else if n % 5 == 0 {
Print("Buzz");
buzzes += 1;
} else {
Print("{}", n);
}
The order of the questions is the whole trick
An else if chain runs the first branch whose condition holds and skips the rest. Fifteen is a multiple of 3, so a chain that asks about 3 first answers "Fizz" for 15 and never gets as far as "FizzBuzz". The most specific question has to come first; the general ones follow.
That is also why the tallies are worth printing. In a correct run there are 6 FizzBuzzes. If you move the % 3 test to the top of the chain, the program still compiles and still prints a hundred answers, but the tally reports Fizz 33 times and FizzBuzz 0 times — every FizzBuzz has been swallowed by Fizz.
Ten to a line
After each answer the loop decides what comes next. Every tenth number ends the line; every other one is followed by a space:
if n % 10 == 0 {
PrintLine();
} else {
Print(" ");
}
Print writes without ending the line, so the answers build up across it until PrintLine() with no arguments ends it. The same % test that finds the multiples of 3 here finds every tenth n.
The program
The whole lesson is one package in the Examples repository. Its comments explain every step.
// FizzBuzz: count from 1 to 100, but say "Fizz" instead of every multiple of 3, "Buzz" instead
// of every multiple of 5, and "FizzBuzz" instead of every multiple of both.
//
// It began as a children's game for practising division, and became the most famous little test
// in programming because it is so easy to get almost right. The trap is the order of the
// questions. Fifteen is a multiple of 3, so a program that asks about 3 first says "Fizz" and
// never gets as far as "FizzBuzz". The multiple of both has to be checked before either one.
//
// Everything here comes from the first three parts: `%` gives the remainder of a division, so
// `n % 3 == 0` means "n divides by 3 exactly"; an `if` / `else if` chain picks the first question
// that answers yes; and a `for` loop walks the numbers.
import Io::{ Print, PrintLine };
func Main() -> int {
var fizzes = 0;
var buzzes = 0;
var fizzBuzzes = 0;
for n in 1..=100 {
// A multiple of both 3 and 5 is a multiple of 15, so one test covers it.
if n % 15 == 0 {
Print("FizzBuzz");
fizzBuzzes += 1;
} else if n % 3 == 0 {
Print("Fizz");
fizzes += 1;
} else if n % 5 == 0 {
Print("Buzz");
buzzes += 1;
} else {
Print("{}", n);
}
// Ten to a line keeps the output short: a space between entries, and a line break after
// every tenth one.
if n % 10 == 0 {
PrintLine();
} else {
Print(" ");
}
}
PrintLine();
PrintLine("Fizz {} times", fizzes);
PrintLine("Buzz {} times", buzzes);
PrintLine("FizzBuzz {} times", fizzBuzzes);
PrintLine("numbers {} times", 100 - fizzes - buzzes - fizzBuzzes);
return 0;
}
Run it
cd Examples/Projects/FizzBuzz
rux run
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz
11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz
Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz
31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz
41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz
Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz
61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz
71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz
Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz
91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
Fizz 27 times
Buzz 14 times
FizzBuzz 6 times
numbers 53 times
Common mistakes
if n % 3 == 0 before if n % 15 == 0 is still valid code, so the compiler cannot help — 15, 30, 45 and the rest come out as Fizz. The tally gives it away: Fizz 33 times, FizzBuzz 0 times. Always order a chain from the most specific case to the least.= where you meant ==.if n % 15 = 0 is an assignment, not a comparison, and is refused: error: operator '=' requires an assignable target, but its left operand has type 'int'. A condition compares with ==.let.The counters change on every pass, so they need
var. With let fizzes = 0; the line fizzes += 1; fails with error: cannot modify immutable variable 'fizzes'.Try it yourself
- Add a fourth rule: say "Bazz" for multiples of 7. Where in the chain does each new test have to go, and what should a multiple of 3, 5 and 7 print?
- Count to 30 instead of 100. The last line of the tally computes the plain numbers as
100 - fizzes - buzzes - fizzBuzzes— what else has to change so the report stays right? - Print five answers to a line instead of ten.
- Rewrite the chain so it never mentions 15: test 3 and 5 on their own, and use
&&for the case where both hold. Check that the tallies come out the same.
Learn more
- Else if — why the first condition that holds wins
- Arithmetic —
%and integer division - If and Arithmetic operators in the Rux Reference
- Next project: Temperature, the checkpoint for Functions