library(dplyr)FizzBuzz
My implementation of FizzBuzz in R, using a vector function.
FizzBuzz
An R implementation of Fizz Buzz, using the instructions from Rosetta Code.
First Implementation
My implementation, written first.
The function:
fizz_buzz <- function(x) {
fb_single <- function(n) {
if (n %% 3 == 0 && n %% 5 == 0) {
"FizzBuzz"
} else if (n %% 5 == 0) {
"Buzz"
} else if (n %% 3 == 0) {
"Fizz"
} else {
# use as.character() so all return values match character(1)
as.character(n)
}
}
vapply(x, fb_single, character(1))
}The task:
fizz_buzz(1:100) [1] "1" "2" "Fizz" "4" "Buzz" "Fizz"
[7] "7" "8" "Fizz" "Buzz" "11" "Fizz"
[13] "13" "14" "FizzBuzz" "16" "17" "Fizz"
[19] "19" "Buzz" "Fizz" "22" "23" "Fizz"
[25] "Buzz" "26" "Fizz" "28" "29" "FizzBuzz"
[31] "31" "32" "Fizz" "34" "Buzz" "Fizz"
[37] "37" "38" "Fizz" "Buzz" "41" "Fizz"
[43] "43" "44" "FizzBuzz" "46" "47" "Fizz"
[49] "49" "Buzz" "Fizz" "52" "53" "Fizz"
[55] "Buzz" "56" "Fizz" "58" "59" "FizzBuzz"
[61] "61" "62" "Fizz" "64" "Buzz" "Fizz"
[67] "67" "68" "Fizz" "Buzz" "71" "Fizz"
[73] "73" "74" "FizzBuzz" "76" "77" "Fizz"
[79] "79" "Buzz" "Fizz" "82" "83" "Fizz"
[85] "Buzz" "86" "Fizz" "88" "89" "FizzBuzz"
[91] "91" "92" "Fizz" "94" "Buzz" "Fizz"
[97] "97" "98" "Fizz" "Buzz"
To solve this, I first wrote the task, then wrote the function. I took advantage of the fact that R will print the return output of a function by default.
For the function, I wanted to use functional programming and avoid a for() loop, and only use base R, so I implemented a function for a single case and used vapply() to apply the function across the vector sequence 1:100. In my original version, I used unlist(lapply()) because I couldn’t get vapply() to work. The help for dplyr::case_when() includes a FizzBuzz example with as.character() so that the return type is always the same; I adapted this to my initial base R solution.
dplyr
Using dplyr::case_when() allows much simpler code: (R doesn’t have a built-in ‘case’ statement)
fizz_buzz_d <- function(x) {
dplyr::case_when(
# x %% 15 == 0 is equivalent to x %% 5 == 0 && x %% 3 == 0
x %% 15 == 0 ~ "FizzBuzz",
x %% 5 == 0 ~ "Buzz",
x %% 3 == 0 ~ "Fizz",
.default = as.character(x)
)
}
fizz_buzz_d(1:100) [1] "1" "2" "Fizz" "4" "Buzz" "Fizz"
[7] "7" "8" "Fizz" "Buzz" "11" "Fizz"
[13] "13" "14" "FizzBuzz" "16" "17" "Fizz"
[19] "19" "Buzz" "Fizz" "22" "23" "Fizz"
[25] "Buzz" "26" "Fizz" "28" "29" "FizzBuzz"
[31] "31" "32" "Fizz" "34" "Buzz" "Fizz"
[37] "37" "38" "Fizz" "Buzz" "41" "Fizz"
[43] "43" "44" "FizzBuzz" "46" "47" "Fizz"
[49] "49" "Buzz" "Fizz" "52" "53" "Fizz"
[55] "Buzz" "56" "Fizz" "58" "59" "FizzBuzz"
[61] "61" "62" "Fizz" "64" "Buzz" "Fizz"
[67] "67" "68" "Fizz" "Buzz" "71" "Fizz"
[73] "73" "74" "FizzBuzz" "76" "77" "Fizz"
[79] "79" "Buzz" "Fizz" "82" "83" "Fizz"
[85] "Buzz" "86" "Fizz" "88" "89" "FizzBuzz"
[91] "91" "92" "Fizz" "94" "Buzz" "Fizz"
[97] "97" "98" "Fizz" "Buzz"
for loop
The simplest way to solve this is with a for loop:
for (n in 1:100) {
if (n %% 3 == 0 && n %% 5 == 0) {
print("FizzBuzz")
} else if (n %% 5 == 0) {
print("Buzz")
} else if (n %% 3 == 0) {
print("Fizz")
} else {
print(n)
}
}[1] 1
[1] 2
[1] "Fizz"
[1] 4
[1] "Buzz"
[1] "Fizz"
[1] 7
[1] 8
[1] "Fizz"
[1] "Buzz"
[1] 11
[1] "Fizz"
[1] 13
[1] 14
[1] "FizzBuzz"
[1] 16
[1] 17
[1] "Fizz"
[1] 19
[1] "Buzz"
[1] "Fizz"
[1] 22
[1] 23
[1] "Fizz"
[1] "Buzz"
[1] 26
[1] "Fizz"
[1] 28
[1] 29
[1] "FizzBuzz"
[1] 31
[1] 32
[1] "Fizz"
[1] 34
[1] "Buzz"
[1] "Fizz"
[1] 37
[1] 38
[1] "Fizz"
[1] "Buzz"
[1] 41
[1] "Fizz"
[1] 43
[1] 44
[1] "FizzBuzz"
[1] 46
[1] 47
[1] "Fizz"
[1] 49
[1] "Buzz"
[1] "Fizz"
[1] 52
[1] 53
[1] "Fizz"
[1] "Buzz"
[1] 56
[1] "Fizz"
[1] 58
[1] 59
[1] "FizzBuzz"
[1] 61
[1] 62
[1] "Fizz"
[1] 64
[1] "Buzz"
[1] "Fizz"
[1] 67
[1] 68
[1] "Fizz"
[1] "Buzz"
[1] 71
[1] "Fizz"
[1] 73
[1] 74
[1] "FizzBuzz"
[1] 76
[1] 77
[1] "Fizz"
[1] 79
[1] "Buzz"
[1] "Fizz"
[1] 82
[1] 83
[1] "Fizz"
[1] "Buzz"
[1] 86
[1] "Fizz"
[1] 88
[1] 89
[1] "FizzBuzz"
[1] 91
[1] 92
[1] "Fizz"
[1] 94
[1] "Buzz"
[1] "Fizz"
[1] 97
[1] 98
[1] "Fizz"
[1] "Buzz"
The downside to this approach is that it prints each result individually, instead of returning a vector.
Rosetta Code
Note: Rosetta Code offers several different solutions for R. The first solution is cleverer yet still understandable use of base R:
fizz_buzz_r <- function(x) {
xx <- x
xx[x %% 3 == 0] <- "Fizz"
xx[x %% 5 == 0] <- "Buzz"
xx[x %% 15 == 0] <- "FizzBuzz"
xx
}
fizz_buzz_r(1:100) [1] "1" "2" "Fizz" "4" "Buzz" "Fizz"
[7] "7" "8" "Fizz" "Buzz" "11" "Fizz"
[13] "13" "14" "FizzBuzz" "16" "17" "Fizz"
[19] "19" "Buzz" "Fizz" "22" "23" "Fizz"
[25] "Buzz" "26" "Fizz" "28" "29" "FizzBuzz"
[31] "31" "32" "Fizz" "34" "Buzz" "Fizz"
[37] "37" "38" "Fizz" "Buzz" "41" "Fizz"
[43] "43" "44" "FizzBuzz" "46" "47" "Fizz"
[49] "49" "Buzz" "Fizz" "52" "53" "Fizz"
[55] "Buzz" "56" "Fizz" "58" "59" "FizzBuzz"
[61] "61" "62" "Fizz" "64" "Buzz" "Fizz"
[67] "67" "68" "Fizz" "Buzz" "71" "Fizz"
[73] "73" "74" "FizzBuzz" "76" "77" "Fizz"
[79] "79" "Buzz" "Fizz" "82" "83" "Fizz"
[85] "Buzz" "86" "Fizz" "88" "89" "FizzBuzz"
[91] "91" "92" "Fizz" "94" "Buzz" "Fizz"
[97] "97" "98" "Fizz" "Buzz"
Of all the solutions, I think using dplyr::case_when() is the most readable. If I needed a base R solution in the future, I’d pick the Rosetta version.