FizzBuzz, part 2: A fancier way

Piggybacking off my earlier post, because I have an obsessive personality I couldn’t help thinking of fancier, if more convoluted, ways to write FizzBuzz. I didn’t like the fact that I had to write the modulo operation and “Fizz” and “Buzz” more than once each. I came up with many variations of the code below (once again, in Kotlin):

val map = mapOf(3 to "Fizz", 5 to "Buzz")

fun main() {
    for (i in 1..100) {
        val fb = StringBuilder()
        map.forEach { if (i % it.key == 0) fb.append(it.value) }
        println(if (fb.isEmpty()) i else fb)
    }
}

Here the code uses a map (a set of key-value pairs) to establish the required relationships: 3 to Fizz, and 5 to Buzz. The outer loop, counting 1 through 100, is the same as before. We initialize an empty StringBuilder, and then start a second, inner loop that goes through each of the two aforementioned key-value pairs in the map and checks it against the current number i. If the operation returns true (that is, i is a multiple of the key of the current pair in the map), the value of the pair is added to the StringBuilder. So, if the operation returns true for the first key-value pair, we get “Fizz.” If only the second, “Buzz.” If both times, we get “FizzBuzz.” And each of these words appear in the code only once. Finally, we check if the string is empty in the end, and if so we just print the current number.

I could just as easily have done string concatenation by first assigning an empty string to a mutable variable (var fb = ""), but for reasons I don’t yet entirely understand, StringBuilder performs better, especially when loops are involved. In a program this small though, nobody will notice… I think?

Another beauty of this approach is that if we wanted to, we can change the rules very easily. We can add a third key-value pair to the map, maybe 7 to “Fuzz,” or use a different map entirely without rewriting anything else. Okay, I’m done with FizzBuzz now, moving on.

FizzBuzz: An intermezzo

Scaring myself with the revelation that many would-be developers ostensibly cannot write FizzBuzz, I became anxious to know if I would pass the test. The task is to write a program in as few characters as possible that will print the numbers 1 to 100 each on a new line, except multiples of 3 become “Fizz,” multiples of 5 are “Buzz,” and multiples of both 3 and 5 are “FizzBuzz.” As it turns out, the solution is nice and short in Kotlin:

fun main() {
    for (i in 1..100) { 
        println(when {
            i % 3 == 0 && i % 5 == 0 -> "FizzBuzz"
            i % 3 == 0 -> "Fizz"
            i % 5 == 0 -> "Buzz"
            else -> i
        })
    }
}

The overall logic is simple enough, just a plain old loop through 1 to 100 and conditionals to determine what to print. But I had to think for a second to remember the modulus operator… Here it means that when i is divided by either 3 or 5 and the remainder is 0, then it is a multiple of 3 or 5. I wonder if there’s an even more concise way to do this.

The when conditional makes things neat, instead of nested if/else if statements. i % 3 == 0 && i % 5 == 0 needs to come first, or else the program will print “Fizz” as long as i is a multiple of 3, regardless of whether it is also a multiple of 5. And so on. Another thing is that if i weren’t pressed for characters, I would maybe write "$i" in that else branch instead of just i to be consistent with the preceding branches, which all result in strings. But this appears to be a non-issue.