Introduction
Raindrops is a slightly more complex version of the FizzBuzz challenge, a classic interview question.
Instructions
Instructions
Your task is to convert a number into its corresponding raindrop sounds.
If a given number:
- is divisible by 3, add “Pling” to the result.
- is divisible by 5, add “Plang” to the result.
- is divisible by 7, add “Plong” to the result.
- is not divisible by 3, 5, or 7, the result should be the number as a string.
Examples
- 28 is divisible by 7, but not 3 or 5, so the result would be
"Plong".
- 30 is divisible by 3 and 5, but not 7, so the result would be
"PlingPlang".
- 34 is not divisible by 3, 5, or 7, so the result would be
"34".
A common way to test if one number is evenly divisible by another is to compare the [remainder][remainder] or [modulus][modulo] to zero.
Most languages provide operators or functions for one (or both) of these.
[remainder]: https://exercism.org/docs/programming/operators/remainder
[modulo]: https://en.wikipedia.org/wiki/Modulo_operation
Dig Deeper
buildString
buildString
object Raindrops {
fun convert(num: Int) = buildString {
if (num % 3 == 0) append("Pling")
if (num % 5 == 0) append("Plang")
if (num % 7 == 0) append("Plong")
if (isEmpty()) append(num)
}
}
An object declaration is used to define Raindrops as essentially a singleton object instantiation of the class.
This is sufficient, since there is no object state that needs to change with each call of the convert method.
The convert function is implemented with a call to the buildString function.
Although the convert function has multiple lines, it consists only of the one buildString expression, so it is defined using
single-expression function syntax, with the curly braces omitted from the convert function call
and the return type inferred.
The builderAction argument is a block of statements, each of which calls one or more methods on an implicit StringBuilder object.
The modulus operator (%) is used to check if the input number is evenly divisible by 3, 5, or 7.
If so, then the append method is called on theStringBuilder to add the associated sound.
After all of the numbers have been checked, the isEmpty method of StringBuilder is used to see if no sound was added.
If no sound was added, then the input number number is automatically converted to a String when appended to the StringBuilder.
The convert function returns the result of calling buildString, which is the result of the implicit call to the toString
method of the StringBuilder after the block of statements in the buildAction argument.
fold on a List
fold on a List
object Raindrops {
fun convert(n: Int) =
listOf(3 to "Pling", 5 to "Plang", 7 to "Plong")
.fold("") { output, pair ->
output + if (n % pair.first == 0) pair.second else ""
}
.ifEmpty { n.toString() }
}
An object declaration is used to define Raindrops as essentially a singleton object instantiation of the class.
This is sufficient, since there is no object state that needs to change with each call of the convert method.
The convert function is implemented with a call to a chain of functions which returns a single value.
Although the convert function has multiple lines, it consists only of the one expression resulting from the function chain,
so it is defined using single-expression function syntax,
with the curly braces omitted from the convert function call and the return type inferred.
The first function is the listOf method to create a List of Pair values,
using the to keyword to associate a number with its sound.
The fold method is called on the List.
Its accumulating value is initialized with an empty String.
The lambda of fold takes the accumulating String value as well as the Pair of each List element being iterated.
If the input number is evenly divisible by the number in the current Pair being iterated, then the sound from the Pair is concatenated
to the accumulating String, otherwise, an empty string is concatenated to it.
The accumulating String is returned to the next iteration of fold.
When fold has iterated through all of the List elements, the StringBuilder is the result.
The convert function returns the result of calling the ifEmpty method on the StringBuilder.
If the StringBuilder content is empty, then it outputs the input number converterd to a String.
Otherwise, it returns the content of the StringBuilder as a String.
Source: Exercism kotlin/raindrops