FizzBuzz Functional Fun in Scala

Hans L'HoestHans L'Hoest
4 min read

Updated with a more functional implementation of FizzBuzz November 2015

Updated with a link to an implementation using Monoids July 2016

FizzBuzz fun in Scala using Scala Streams.

The straightforward implementation of FizzBuzz usually involves defining a list or array of fixed size 100, populating it using a loop over the index and setting the value in the list according to our Fizz Buzz specification.

Streams are lazy lists in which elements are only evaluated when they are needed. This allows for a seemingly infinite recursive loop-looking definition as shown in the Fibonacci example below. The first line builds a sequence of sums, the sum of a and fibFrom looks as it if will never end if not for the lazy evaluation.

def fibFrom(a: Int, b: Int): Stream[Int] = a #:: fibFrom(b, a + b)

def fibonacciStream(n: Int) = fibFrom(1, 1).take(n).toList.last

The 2nd line is there for clarity to show how to calculate the nth Fibonacci number based on our Stream definition. The take method will return a Stream, so nothing is being evaluated until toList is called. (Note that in case of an infinite collection toList may never terminate.)

Here is an alternate implementation of FizzBuzz using the Stream class in the standard Scala API.

def fizzbuzz(s: Int): List[String] = {

  def shout(i: Int): String =
    if (i % 15 == 0) "FizzBuzz" else
    if (i % 3 == 0) "Fizz" else
    if (i % 5 == 0) "Buzz" else
      i.toString

  val fb: Stream[String] = Stream.from(1).map(i => shout(i))

  (fb take s).toList
}

Stream.from(start:Int) creates an infinite stream of integers and we map them using a function according to the FizzBuzz specification. We then take the first n of this infinite list and convert it to a 'normal' Scala List.

To print the first 100:

fizzbuzz(100).foreach{ println(_) }

As a little extra, this is how we could test our FizzBuzz implementation using ScalaCheck:

import org.scalacheck.Gen
import org.scalatest.FunSuite
import org.scalacheck.Prop.forAll
import org.scalatest.prop.Checkers

class FizzBuzzTest extends FunSuite with Checkers {

  test("fizzbuzz") {
    val fb = fizzbuzz(100)
    val range = Gen.choose[Int](1, 100)
    val fizzbuzzProperty = forAll(range) {
      n =>
        if (n % 15 == 0) fb(n - 1) == "FizzBuzz" else
        if (n % 5 == 0) fb(n - 1) == "Buzz" else
        if (n % 3 == 0) fb(n - 1) == "Fizz" else
          fb(n - 1) == n.toString

    }
    check(fizzbuzzProperty)
  }
}

A more functional implementation of FizzBuzz (added November 2015)

Thanks to Dierk König's implementation in Frege:

  def fizzbuzz(s: Int): List[String] = {

    // helper method inspired by haskell, cycle a list infinitely,
    def cycle(xs: List[String]): Stream[String] = Stream.continually(xs).flatten

    val numbers = Stream.from(1)

    // a infinite cycle of "", "", "Fizz"
    val fizzes = cycle(List("", "", "Fizz"))
    // a infinite cycle of "", "", "", "", "Buzz"
    val buzzes = cycle(List("", "", "", "", "Buzz"))

    // zip the fizzes and buzzes, and concatenate them, result is "", "", "Fizz", "", "Buzz", "Fizz", ...
    val pattern = fizzes zip buzzes map { case (f, b) => f + b }
    // zip numbers with the pattern, if the pattern is empty keep the number, otherwise keep the pattern
    val numbersAndPattern = numbers zip pattern map {
      case (n, p) => if (p.isEmpty) n.toString else p
    }

    numbersAndPattern take s toList
  }

What I like about this implementation:

  • Much fewer conditionals. There is only 1 compared to 4 in the first implementation. And the order matters in the latter, if I do not put the i % 15 == 0 check first the logic will fall apart. So if changes need to be made it is easier to introduce bugs in the one containing more conditionals.

  • The code can be more easily built incrementally using the REPL. It just flows nicer. The shout method needs to be entered in one go, all or nothing.

  • Closer to the specification. Consider the i % 15 == 0 check in the first implementation a bit more: to fit the FizzBuzz specification better it would be more accurate to write it as i % 3 == 0 || i % 5 == 0. This would up the conditional checks to 5 though. At first sight, the concatenation in the functional implementation felt like a lucky shot, but in fact, it fits exactly the specification of FizzBuzz: I suppose it is no coincidence we are shouting 'FizzBuzz', a concatenation, instead of 'Boo!'.

Note there is also zipWithIndex in Scala but I maintained the same "zip and map"-logic to keep the code more consistent and hence more simple.

A functional implementation using Monoids (Added July 2016)

Monoids also provide a way of implementing FizzBuzz in a more functional way, check it out here. At the moment I do not have the time to go into detail but it is a nice example of practical use of monoids.

0
Subscribe to my newsletter

Read articles from Hans L'Hoest directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Hans L'Hoest
Hans L'Hoest

I write about: Software architecture and engineering, Better software better. DDD, Scala and Rust