ネタ元:「fizzbuzzについて思うこと」
TypeScript版:【TypeScript】仕様変更に強い FizzBuzz
更に仕様変更に強くした版:【Kotlin】更に仕様変更に強い FizzBuzz
FizzBuzz の、割る数、出力する文字列、変換規則の数や順番が変わっても
最小限のコード変更で済むようにする。
/**
* FizzBuzz を行うためのクラス。
*
* [invoke] 関数に数値を与えると対応する文字列を返す。
*/
class FizzBuzz private constructor(
private val fizzBuzzMap: List<Pair<Int, String>>
) {
/**
* @param fizzBuzzMap 割る数と、
* それで割り切れたときに出力する文字列の組の列。
*/
constructor(
fizzBuzzMap: Iterable<Pair<Int, String>>
) : this(fizzBuzzMap.toList())
/**
* @param fizzBuzzMap 割る数と、
* それで割り切れたときに出力する文字列の組の列。
*/
constructor (
vararg fizzBuzzMap: Pair<Int, String>
) : this(fizzBuzzMap.toList())
/** 与えられた数値に対応する文字列を返す。 */
operator fun invoke(num: Int): String =
fizzBuzzMap.asSequence()
.mapNotNull { (divisor, str) ->
if (num % divisor == 0) str
else null
}
.joinToString("")
.takeUnless { it.isEmpty() }
?: num.toString()
}
普通の FizzBuzz
/** 変換規則の定義。 */
val fizzBuzz = FizzBuzz(
3 to "Fizz",
5 to "Buzz"
)
fun main() {
(1..15).asSequence()
.map {
fizzBuzz(it)
}.forEach {
println(it)
}
}
出力
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
割る数と出力する文字列を変更
/** 変換規則の定義。 */
val fizzBuzz = FizzBuzz(
7 to "Foo",
2 to "Bar"
)
// main 関数は同じなので省略
出力
1
Bar
3
Bar
5
Bar
Foo
Bar
9
Bar
11
Bar
13
FooBar
15
こんなことも
val fizzBuzz = FizzBuzz(
1 to "<",
3 to "Fizz",
5 to "Buzz",
1 to ">"
)
// main 関数は同じなので省略
出力
<>
<>
<Fizz>
<>
<Buzz>
<Fizz>
<>
<>
<Fizz>
<Buzz>
<>
<Fizz>
<>
<>
<FizzBuzz>
/以上