# General FizzBuzz in Scala

I wanted to create a FizzBuzz implementation that both showcases the strengths of Scala (Functional paradigm and collections) and is general enough to anticipate the typical interview follow-up questions. i.e. What if fizz was for factors of 4 instead? What if we wanted to replace factors of 7 with "foo"?

object FizzBuzz extends App {

def fizzbuzz(factors: Map[Int, String])(currentNumber: Int): String = {
val words = factors.filter(currentNumber % _._1 == 0).values
if (words.isEmpty) currentNumber.toString else words.mkString("")
}

private final val Factors = Map(3 -> "fizz", 5 -> "buzz")
private final val Range = 1 to 100

Range.map(fizzbuzz(Factors)).foreach(println)
}


I would appreciate any feedback on how I can make my Scala more idiomatic.

Map is not guaranteed to impose or preserve any order for its entries. For example, if I change Factors to …

private final val Factors = Map(3 -> "a", 5 -> "b", 6 -> "c", 7 -> "d", 8 -> "e", 9 -> "f")


… I get:

⁞
89
bcfa
d
92
a
94
b
cae
97
d
fa
b


So, the fact that you get "fizzbuzz" rather than "buzzfizz" is based on luck, not skill. If you want to guarantee "fizzbuzz", you need a scala.collection.immutable.SortedMap.

Because you want to be able to change the mapping of fizz and buzz I would think to make a funcion that take a function as an argument that maps a number to a string:

def fizzbuzz(countUntil: Int)(mapping: Int => String) = {
for (i <- 0 to countUntil) yield mapping(i)
}


Then you can call the function like this:

// Map Int to String using pattern matching with a guard
fizzbuzz(30) {
case fizzbuzz if fizzbuzz % 3 == 0 && fizzbuzz % 5 == 0 => "fizzbuzz"
case fizz if fizz % 3 == 0 => "fizz"
case buzz if buzz % 5 == 0 => "buzz"
case f => s"$f" }.foreach(println)  The pattern matching code could be an if/else just as long as it takes an Int and returns a String for example: // Map Int to String using if/else fizzbuzz(30){ f => if (f % 3 == 0 && f % 5 == 0) "fizzbuzz" else if (f % 3 == 0) "fizz" else if (f % 5 == 0) "buzz" else s"$f"
}.foreach(println)

• That's a terrible use of pattern matching. – Nico Nov 1 '17 at 12:37
• @Nico What makes it so terrible? – Soapy Nov 1 '17 at 13:36
• you're just wrapping an if then else into a pattern matching for no added benefit – Nico Nov 1 '17 at 14:08
• @Nico If you're going for performance or if you perfer the syntax then go for an if/else however I pefer the pattern matching in this case. But for a complete example I've added an if/else version to my answer. – Soapy Nov 1 '17 at 14:25
• @Soapy The main drawback I see with your approach is that the number of cases grows drastically when there are more possible factors. For example, if I wanted factors of 3 -> "fizz", 4 -> "buzz", 5 -> "foo", 6 -> "bar", you would need an if case for each combination of those options. (case 3, case 3&4, case 3&5, case 3&4&5 ...) which would be difficult to maintain. Although I appreciate the suggestion! – Taylor Nov 1 '17 at 16:37