UPDATED BY
Brennan Whitfield | Jul 21, 2023

The FizzBuzz problem is a classic test given in coding interviews. Based on a children’s word game that helps teach division, the FizzBuzz problem is simple: Print integers one-to-N, but print “Fizz” if an integer is divisible by three, “Buzz” if an integer is divisible by five, and “FizzBuzz” if an integer is divisible by both three and five.

There are many ways to achieve the desired output, but some methods are better than others. Great solutions to FizzBuzz don’t just work, they adhere to good programming principles, allow flexibility for later changes and play to a language’s strengths. With these things in mind, solving FizzBuzz is a great exercise for learning the specifics of a language and improving your programming.

What Is FizzBuzz?

FizzBuzz is a common coding task given during interviews that tasks candidates to write a solution that prints integers one-to-N, labeling any integers divisible by three as “Fizz,” integers divisible by five as “Buzz” and integers divisible by both three and five as “FizzBuzz.” Understanding how to solve it can help reinforce good coding practices.

I’ll explain five approaches to the FizzBuzz problem using R. Understanding each one will help to reinforce good coding practices and make use of R’s unique features. It might even help you get hired.

 

How to Solve FizzBuzz 

1. A Naive Solution

The most obvious way to solve FizzBuzz is to loop through a set of integers. In this loop, we use conditional statements to check whether each integer is divisible by three and/or five.

fbnums <- 1:50
output <- vector()

for (i in fbnums) {
  if (i %% 3 == 0 && i %% 5 == 0) {
    output[i] <- "FizzBuzz"
  } else if (i %% 3 == 0) {
    output[i] <- "Fizz"
  } else if (i %% 5 == 0) {
    output[i] <- "Buzz"
  } else {
    output[i] <- i
  }
}

print(output)

The code above takes this approach. First, we store integers one-to–50 in the vector fbnums. An empty vector named output is also defined to store the results of the procedure. Then, we check whether each integer in fbnums is evenly divisible by three and/or five using conditional statements within a for loop. These statements use the modulo operator %%, which returns the remainder of a division operation. As an example, the expression if (i %% 3 == 0) means, “If we divide this integer by three, is the remainder zero?”

When one of the conditional statements returns true, the appropriate response is stored in the ith index of the output vector. Once the loop has completed, we print output to display the results of the process.

FizzBuzz for integers 1–50 printed as a vector
FizzBuzz for integers 1–50, printed as a vector. | Image: Rory Spanton

While this code works, it has several limitations:

  • It uses a lot of messy conditional statements, which are hard to maintain.
  • The statements i %% 3 == 0 and i %% 5 == 0 are repeated twice, making the code inefficient and verbose.
  • The for loop is relatively slow and inefficient in R, especially in cases with many iterations.

Luckily, there are a few ways to improve upon this starting point.

More Coding Interview Questions21 Java Interview Questions for Junior and Senior Developers

 

2. A Better Solution Using a For Loop

It’s possible to reduce the number of conditional statements in our for loop, as shown below. 

fbnums <- 1:50
output <- vector()

for (i in fbnums) {
  output[i] <- ""
  
  if (i %% 3 == 0) {output[i] <- paste0(output[i], "Fizz")}
  if (i %% 5 == 0) {output[i] <- paste0(output[i], "Buzz")}
  if (output[i] == "") {output[i] <- i}
}

print(output)

Here, fbnums and output are defined as they were before. But in the for loop, things work a little differently. First, we define the ith index in our output vector as a blank string. We then check whether our integer is divisible by three as in the last example. If this returns true, we paste “Fizz” onto the end of the blank string in output[i]. We can then evaluate the equivalent statement for five and “Buzz” in the next line. Finally, we check whether output[i is empty. If so, we store the integer in this element to avoid returning a blank string. Once the loop is over, printing output gives the same result as the previous example.

This implementation is better than the previous for a couple reasons:

  • Pasting “Fizz” and “Buzz” onto a blank string like this eliminates the need for a statement evaluating “FizzBuzz.” This removes  repetition and looks neater.
  • The format makes adding extra conditions trivial, while keeping the code readable.

This is good progress, but the use of a for loop still doesn’t leverage some of R’s unique features. The next three examples take full advantage of these and are great for picking up some advanced R techniques.

 

3. A Package Solution Using FizzBuzzR

One of R’s strengths is its variety of user-friendly packages. FizzBuzzR is one of these, and it contains a single function meant for tackling the FizzBuzz problem. Calling fizzbuzz allows the user to specify the range of integers to evaluate, the interval by which to step through these integers and the divisors for “Fizz” and “Buzz.” The output is then printed line-by-line in the console.

# Only needed if you haven't previously installed fizzbuzzR
install.packages("fizzbuzzR")

library(fizzbuzzR)

fizzbuzz(start = 1, end = 50, step = 1, mod1 = 3, mod2 = 5)

This implementation has the obvious advantage of being incredibly concise. But there’s a tradeoff: There are limited options for customization. Let’s say an interviewer asks you to replace “Fizz” with “Biff,” or to store the output straight to a list. In these cases, you’d have to think of a completely new approach to do these things.

 

4. A Functional Solution Using map()

Rather than using a pre-written function, we can write our own FizzBuzz function and then apply this to each integer we want to evaluate.

library(tidyverse)

fbnums <- 1:50

fbmap <- function(input, mod1, mod2, exp1, exp2) {
  output <- ""
  
  if (input %% mod1 == 0) {output <- paste0(output, exp1)}
  if (input %% mod2 == 0) {output <- paste0(output, exp2)}
  if (output == "") {output <- as.character(input)}
  
  return(output)
}

output <- map_chr(fbnums, ~ fbmap(.x, 3, 5, "Fizz", "Buzz"))
print(output)

In the code above, we create a function called fbmap that evaluates a given integer according to our FizzBuzz rules. Our function does this using the same conditional statements in our second example. This time around, however, we replace certain values with arguments that we can pass into the function. Our divisors, three and five, are replaced with the arguments mod1 and mod2, and our print statements “Fizz” and “Buzz” are replaced with exp1 and exp2. This means that when we call the function, we can define these values as whatever we like without having to rewrite lots of code.

To get our output, we apply our function to each element of the fbnums vector using map_chr. We use the expression ~ fbmap(.x, 3, 5, "Fizz", "Buzz") inside map_chr to do this. This tells fbmap to evaluate each element of the fbnums vector (denoted as .x ) with the divisors three and five and responses “Fizz” and “Buzz.” The results of these successive function calls are stored as separate elements in output, a character vector. Printing output then displays the correct results in the console.

This implementation is great for a few reasons:

  • It’s clear, concise and avoids repetition.
  • Specifying arguments to fbmap provides flexibility. New conditions can also be added without complicating the codebase too much.
  • It uses map_chr to apply a function across a vector, which is more efficient than using a for loop in R.

To me, this is a fairly strong FizzBuzz solution. It looks good, makes the most of R, and it isn’t any longer than the naive implementation in my first example. But what if you’d like your FizzBuzz solution to be optimally compatible with a tidyverse workflow?

 

5. A Vectorized Solution Using case_when()

For most tasks in R, there’s a pre-defined tidyverse function that’ll help you out. If you want to apply some if statements to elements of a vector, use case_when from the dplyr package.

library(tidyverse)

fbnums <- 1:50

output <- case_when(fbnums %% 15 == 0 ~ "FizzBuzz",
          fbnums %% 3 == 0 ~ "Fizz",
          fbnums %% 5 == 0 ~ "Buzz",
          TRUE ~ as.character(fbnums))

print(output)

The code above is modified from an example in the case_when documentation written by Hadley Wickham, a statistician and chief data scientist for RStudio. Simply put, case_when applies if statements across a vector and returns an output based on the result of these statements. This example also makes sure to return the integer in question when it isn’t evenly divisible, with the expression TRUE ~ as.character(fbnums). Minus some different syntax, this is exactly what we’ve been doing in the previous examples. The difference is that case_when makes full use of R’s vectorization capabilities, making it more efficient than the for loops in solutions one and two.

On top of this, we still don’t repeat any conditional statements. Although we evaluate “FizzBuzz” as a separate condition, we can use simple math to deduce that any instance of “FizzBuzz” is evenly divisible by 15, the lowest common factor of three and five. This avoids the need for repeating statements containing %% 3 == 0 and %% 5 == 0. The code is still easy to read and to add to if necessary. You can add more conditions to case_when, or pipe to another function after case_when to fulfill more complicated requirements. All in all, case_when is a great function for solving the FizzBuzz problem in R.

The basics of FizzBuzz and how to solve it. | Video: Tom Scott

 

How to Identify the Best FizzBuzz Solution

Solving the FizzBuzz problem demonstrates the value of learning to write neat code. While every solution above works, some are far easier to maintain in a large real-life codebase. Why are these implementations better? They adhere to good programming principles, and make the most of R’s capabilities.

So the next time you code something, interview task or otherwise, ask yourself a few things. Am I repeating myself? How can I play to the strengths of my chosen language? Is the code I’m writing easy to maintain? Answering these questions won’t just help you write a good FizzBuzz solution, they’ll make you a better programmer.

Ace Your Coding Interview5 Job Interview Questions Slack Asks Software Engineers

 

Origin of FizzBuzz

FizzBuzz originated as a word game played by children and students to help them learn division and multiplication concepts. In this game, players sit in a group and count from the number one upwards, each taking a turn to say the next number in sequence. If the number is a multiple of three, the player speaking says “fizz,” if the number is a multiple of five, they say “buzz,” and if the number is a multiple of both three and five, they say “fizz-buzz.” 

FizzBuzz as a job interview question was created by Imran Ghory in 2007, as he outlined in a blog post how the game’s idea could be used to identify developers who struggle to code even “with tiny problems.” On the FizzBuzz WikiWikiWeb page attached on Ghory’s website, it states that the FizzBuzz test is intended to “help filter out the 99.5 percent of programming job candidates who can’t seem to program their way out of a wet paper bag.”

Since its creation, FizzBuzz has been used as a standard coding interview question to gauge how quickly and effectively candidates can solve common coding problems, if at all.

 

Frequently Asked Questions

Why is FizzBuzz used in interviews?

FizzBuzz is used as a general screening tool in coding interviews to determine how efficiently — or even if — candidates can solve basic programming problems.

How difficult is FizzBuzz to solve?

The difficulty of solving FizzBuzz will vary depending on a candidate's coding skills, but is considered to be simple to solve for those having fundamental programming knowledge. For new or entry-level programmers, FizzBuzz may be a challenging problem and take up to a few minutes to solve.

Expert Contributors

Built In’s expert contributor network publishes thoughtful, solutions-oriented stories written by innovative tech professionals. It is the tech industry’s definitive destination for sharing compelling, first-person accounts of problem-solving on the road to innovation.

Learn More

Great Companies Need Great People. That's Where We Come In.

Recruit With Us