By Susam Pal on 20 November 2025
Fizz Buzz is a counting game that has become strangely popular in the world of computer programming as a simple test of basic programming skills. The rules of the game are simple. Players say numbers out loud, starting with one. Whenever a number is divisible by 3, they say ‘fiz’ in its place. If it’s divisible by 5, they say ‘buzz’. If it is divisible by both 3 and 5, the player says both ‘fizz’ and ‘buzz’. Here is a typical Python program that prints this sequence:
for n in range(1, 101):
if n % 15 == 0:
print('FizzBuzz')
elif n % 3 == 0:
print('Fizz')
elif n % 5 == 0:
print('Buzz')
else:
print(n)
Here is the output: fizz-buzz.txt. Can we make the program more complex? Perhaps we can use trigonometric functions to encode all four cases into a single closed-form expression. This is what we are going to know in this article. Finally, we will get a finite Fourier series that can take any integer \( n \) and select the text to be printed.
Contents
definitions
Before proceeding further, let us establish a precise mathematical definition for the Fizz Buzz sequence. We start by introducing some functions that will help us define the fizz buzz sequence later.
symbol function
We define a set of four functions for integers \( n \) \( \{ s_0, s_1, s_2, s_3 \} \) thus: \begin{ign*} s_0(n) &= n, \ s_1(n) &= \mathtt{Fizz}, \ s_2(n) &= \mathtt{Buzz}, \ s_3(n) &= \mathtt{FizzBuzz}. \end{align*} We call these symbol functions because they produce each word that appears in the Fizz Buzz sequence. The symbol function \( s_0 \) itself returns \( n \). The functions \( s_1, \) \( s_2 \) and \( s_3 \) are static functions that always return the literal words \( \mathtt{Fizz}, \) \( \mathtt{Buzz} \) and \( \mathtt{FizzBuzz} \) no matter what the value of \( n \).
Fizz Buzz Sequence
Now we can define the fizz buzz sequence as the sequence \[
(s_{f(n)}(n))_{n = 1}^{\infty}
\]
Where \[
f(n) = \begin{cases}
1 & \text{if } 3 \mid n \text{ and } 5 \nmid n, \\
2 & \text{if } 3 \nmid n \text{ and } 5 \mid n, \\
3 & \text{if } 3 \mid n \text{ and } 5 \mid n, \\
0 & \text{otherwise}.
\end{cases}
\]
The notation \( m \mid n \) means that the integer \( m \) divides the integer \( n, \) i.e. \( n \) is a multiple of \( m. \). Equivalently, there exists an integer \( c \) such that \( n = cm . \) Similarly, \( m \nmid n \) means that \( m \) does not divide \( n, \) i.e. \( n \) is not a multiple of \( m. \) With the above definitions, we can expand the first few terms of the sequence explicitly as follows: \begin{alignment*} (s_{f(n)}(n))_{n = 1}^{\infty} &= (s_{f(1)}(1), \; s_{f(2)}(2), \; s_{f(3)}(3), \; s_{f(4)}(4), \;s_{f(5)}(5), \;s_{f(7)}(7), \; \\ &= (1, \; 2, \; \mathtt{Fizz}, \; 4, \; \mathtt{Fizz}, \; \dots} Notice how the function \( f(n) \) produces the symbol function \( s_i \)
indicator function
Here is the function \( f(n) \) from the previous section, whose cases and conditions have been rearranged to make interesting patterns easier to recognize: \[
f(n) = \begin{cases}
0 & \text{if } 5 \nmid n \text{ and } 3 \nmid n, \\
1 & \text{if } 5 \nmid n \text{ and } 3 \mid n, \\
2 & \text{if } 5 \mid n \text{ and } 3 \nmid n, \\
3 & \text{if } 5 \mid n \text{ and } 3 \mid n.
\end{cases}
\]
This function helps us to select another function \( s_{f(n)}(n) \) which in turn determines the \( n \)th term of the fizz buzz sequence. Our goal now is to replace this piecewise formula with a single closed-form expression. To do this, we first define the indicator function \( I_m(n) \) as follows: \[
I_m(n) = \begin{cases}
1 & \text{if } m \mid n, \\
0 & \text{if } m \nmid n.
\end{cases}
\]
The formula for \( f(n) \) can now be written as: \[
f(n) = \begin{cases}
0 & \text{if } I_5(n) = 0 \text{ and } I_3(n) = 0, \\
1 & \text{if } I_5(n) = 0 \text{ and } I_3(n) = 1, \\
2 & \text{if } I_5(n) = 1 \text{ and } I_3(n) = 0, \\
3 & \text{if } I_5(n) = 1 \text{ and } I_3(n) = 1.
\end{cases}
\]
Do you see any patterns? Here the same function is written in table form:
| \( I_5(n) \) | \( I_3(n) \) | \( f(n) \) |
|---|---|---|
| \( 0 \) | \( 0 \) | \( 0 \) |
| \( 0 \) | \( 1 \) | \( 1 \) |
| \( 1 \) | \( 0 \) | \( 2 \) |
| \( 1 \) | \( 1 \) | \( 3 \) |
Do you see it now? If we consider the values of the first two columns as binary digits and the values of the third column as decimal numbers, then the first two columns in each row give the binary representation of the number in the third column. For example, \( 3_{10} = 11_2 \) and indeed in the last row of the table, we see the bits \( 1 \) and \( 1 \) in the first two columns and the number \( 3 \) in the last column. In other words, writing the binary digits \( I_5(n) \) and \( I_3(n) \) together gives us the binary representation of \( f(n). \) Hence \[
f(n) = 2 \, I_5(n) + I_3(n).
\]
Now we can write a small program to display this formula:
for n in range(1, 101):
s = [n, 'Fizz', 'Buzz', 'FizzBuzz']
i = (n % 3 == 0) + 2 * (n % 5 == 0)
print(s[i])
We can narrow it down even further, at the expense of some clarity:
for n in range(1, 101):
print([n, 'Fizz', 'Buzz', 'FizzBuzz'][(n % 3 == 0) + 2 * (n % 5 == 0)])
What we have achieved so far is quite good. Although there is no universal definition of a closed-form expression, I think most people would agree that the indicator functions defined above are simple enough to be allowed in closed-form expressions.
complex exponent
In the previous section, we obtained the formula \[
f(n) = I_3(n) + 2 \, I_5(n)
\]
Which we use as an index to look for the text to be printed. We also argued that this is already a very good closed-form expression.
However, in the interest of making things more complicated, we should ask ourselves: what if we are not allowed to use indicator functions? What if we must follow the generally accepted meaning of a closed-form expression that allows basic operations such as addition, subtraction, multiplication, division, integer exponents and roots with integer indices, as well as only limited combinations of operations such as exponential, logarithmic and trigonometric functions. It turns out that the above formula can be rewritten using only addition, multiplication, division and cosine functions. Let’s start translating. Consider Yoga\[
S_m(n) = \sum_{k = 0}^{m – 1} e^{2 \pi i k n / m},
\]
Where \( i \) is the imaginary unit and \( n \) and \( m \) are integers. This is a geometric series in the complex plane whose ratio is \( r = e^{2 \pi in / m}. \) If \( n \) is a multiple of \( m , \) then \( n = cm \) for some integer \( c \) and we get \[
r
= e^{2 \pi i n / m}
= e^{2 \pi i c}
= 1.
\]
Therefore, when \( n \) is a multiple of \( m, \) we get \[
S_m(n)
= \sum_{k = 0}^{m – 1} e^{2 \pi i k n / m}
= \sum_{k = 0}^{m – 1} 1^k
= m.
\]
If \( n \) is not a multiple of \( m, \) then \( r \ne 1 \) and the geometric series becomes \[
S_m(n)
= \frac{r^m – 1}{r – 1}
= \frac{e^{2 \pi i n} – 1}{e^{2 \pi i n / m} – 1}
= 0.
\]
so, \[
S_m(n) = \begin{cases}
m & \text{if } m \mid n, \\
0 & \text{if } m \nmid n.
\end{cases}
\]
Dividing both sides by \( m, \) we get \[
\frac{S_m(n)}{m} = \begin{cases}
1 & \text{if } m \mid n, \\
0 & \text{if } m \nmid n.
\end{cases}
\]
But on the right side \( I_m(n). \) so \[
I_m(n)
= \frac{S_m(n)}{m}
= \frac{1}{m} \sum_{k = 0}^{m – 1} e^{2 \pi i k n / m}.
\]
cosine
We start with Euler’s formula\[
e^{i x} = \cos x + i \sin x
\]
Where \( x \) is a real number. From this formula we get[
e^{i x} + e^{-i x} = 2 \cos x.
\]
So \begin{align*} I_3(n) &= \frac{1}{3} \sum_{k = 0}^2 e^{2 \pi ikn / 3} \\ &= \frac{1}{3} \left( 1 + e^{2 \pi in / 3} + e^{4 \pi in / 3} \right) \\ &= \frac{1}{3} \left( 1 + e^{2 \pi in / 3} + e^{-2 \pi in / 3} \right) \ &= \frac{1}{3} + \frac{2}{3} \cos \left( \frac{2 \pi n}{3} \right). \end{align*} The third equality above follows from the fact that \( e^{4 \pi in / 3} = e^{6 \pi in / 3} e^{-2 \pi in / 3} = e^{2 \pi in} e^{-2 \pi in/3} = e^{-2 \pi in / 3}. \)
The above function is defined for integer values of \( n \), but we can extend its formula to real \( x \) and plot it to observe its shape between integers. As expected, the function takes the value \( 1 \) whenever \( x \) is an integer multiple of \( 3 \) and \( 0 \) whenever \( x \) is an integer that is not divisible by \( 3. \)

\( \frac{1}{3} + \frac{2}
Similarly,\begin{align*} \frac{1}{5} \left( 1 + e^{2 \pi in / 5} + e^{4 \pi in / 5} + e^{-4 \pi in / 5} + e^{-2 \pi in / 5} \right) \ &= \frac{1}{5} + \frac{2}{5} \cos \left( \frac{2 \pi n}{5} \right) + \frac{2}{5} \cos \left( \frac{4 \pi n}{5} \right). \end{align*} Expanding this expression to real values of \( x \) allows us to plot its shape as well. Once again, the function takes the value of \( 1 \) on integer multiples of \( 5 \) and \( 0 \) on integers not divisible by \( 5. \).

\( \frac{1}{5} + \frac{2}{5} \cos \left( \frac{2 \pi x}{5} \right) + \frac{2}
Recall that we expressed \( f(n) \) as[
f(n) = I_3(n) + 2 \, I_5(n).
\]
Substituting these trigonometric expressions gives \[
f(n)
= \frac{1}{3} + \frac{2}{3} \cos \left( \frac{2 \pi n}{3} \right) +
2 \cdot \left( \frac{1}{5} + \frac{2}{5} \cos \left( \frac{2 \pi n}{5} \right) +
\frac{2}{5} \cos \left( \frac{4 \pi n}{5} \right) \right).
\]
A straightforward simplification gives[
f(n)
= \frac{11}{15} +
\frac{2}{3} \cos \left( \frac{2 \pi n}{3} \right) +
\frac{4}{5} \cos \left( \frac{2 \pi n}{5} \right) +
\frac{4}{5} \cos \left( \frac{4 \pi n}{5} \right).
\]
We can extend this expression to real \( x \) and plot it as well. The resulting curve takes values \( 0, 1, 2 \) and \( 3 \) at desired integer points.

\( \frac{11}{15} + \frac{2}
Now we can write our Python program like this:
from math import cos, pi
for n in range(1, 101):
s = [n, 'Fizz', 'Buzz', 'FizzBuzz']
i = round(11 / 15 + (2 / 3) * cos(2 * pi * n / 3)
+ (4 / 5) * cos(2 * pi * n / 5)
+ (4 / 5) * cos(4 * pi * n / 5))
print(s[i])
conclusion
Briefly, we have defined the fizz buzz sequence as[
(s_{f(n)}(n))_{n = 1}^{\infty}
\]
Where \[
f(n)
= \frac{11}{15} +
\frac{2}{3} \cos \left( \frac{2 \pi n}{3} \right) +
\frac{4}{5} \cos \left( \frac{2 \pi n}{5} \right) +
\frac{4}{5} \cos \left( \frac{4 \pi n}{5} \right)
\in \{ 0, 1, 2, 3 \}
\]
And \( s_0(n) = n, \) \( s_1(n) = \mathtt{Fizz}, \) \( s_2(n) = \mathtt{Buzz} \) and \( s_3(n) = \mathtt{FizzBuzz}. \) A Python program to print the Fizz Buzz sequence based on this definition was presented earlier. That program can be written more concisely as:
from math import cos, pi
for n in range(1, 101):
print([n, 'Fizz', 'Buzz', 'FizzBuzz'][round(11 / 15 + (2 / 3) * cos(2 * pi * n / 3) + (4 / 5) * (cos(2 * pi * n / 5) + cos(4 * pi * n / 5)))])
If you want to share it with your friends and family and surprise them we can also wrap it up nicely in a one-liner:
printf 'from math import cos, pi\nfor n in range(1, 20):\n print([n, "Fizz", "Buzz", "FizzBuzz"][round(11/15 + (2/3) * cos(2*pi*n/3) + (4/5) * (cos(2*pi*n/5) + cos(4*pi*n/5)))])' | python3
Those with a keen eye can see that the expression we have obtained for \( f(n) \) is a finite Fourier series. This is not surprising, since the output of the Fizz Buzz program depends only on \( n \bmod 15. \). Any function on a finite cyclic group can be written exactly as a finite Fourier expansion.
We’ve taken a simple counting game and turned it into a trigonometric construction: a finite Fourier series with a constant term \( 11/15 \) and three cosine terms with coefficients \( 2/3, \) \( 4/5 \) and \( 4/5. \) None of this makes Fizz Buzz any easier, of course, but it shows that each \( \mathtt{Fizz} \) and \( \mathtt{Buzz} \) is now due to a special set of Fourier coefficients. We started with the modest goal of making this simple problem more complex. I think it’s safe to say we didn’t fall short.