眠れない夜ってFizzBuzzを書きたくなりますよね。いままでさんざんFizzBuzzを書いてきましたが僕はまだ書き足りないです。
今回はきしださんが今年の1月に書いたらしいFizzBuzzをさっき知って「うむ、これこそ2021年のFizzBuzzだ」と思ったので、臆面もなくぱくることにいたししました。
今回のFizzBuzzのコンセプトは以下の通りです。
- 元コードの魂を受け継ぎ、オブジェクト指向は時代に合ってないので
new
を使わない - 元コードの魂は受け継がず、シンプルではなく凝ったことをしており、エレガントではない
- 元コードの魂は受け継がず、動く
また、判定方法は概ねきしださんのコードから拝借していますがループ方法は異っています。
PHPコード
このコードに実用的な要素はありません
<?php
class FizzBuzz
{
public static function __callStatic(string $n, array $args): void
{
echo match ($n % 3) {
0 => match ($n % 5) {
0 => self::fizz_buzz($n),
default => self::fizz($n),
},
default => match ($n % 5) {
0 => self::buzz($n),
default => ($p = strval($n - 1) and self::{$p}()) ?: $n,
},
}, PHP_EOL;
}
public static function fizz(int $n): string
{
// fizzの直後にfizzが来ることはない
if ($n % 5 == 0) {
return self::buzz($n - 1);
}
$_ = fn($n): string => $n;
self::{$_($n-1)}();
return ucfirst(__FUNCTION__);
}
public static function buzz(int $n): string
{
// buzzの直後にbuzzが来ることはない
if ($n % 3 == 0) {
echo self::fizz($p), PHP_EOL;
}
$_ = fn($n): string => $n;
self::{$_($n-1)}();
return ucfirst(__FUNCTION__);
}
public static function fizz_buzz(int $n): string
{
$_ = fn($n): string => $n;
// fizzbuzzの直後はnのみ
self::{$_($n-1)}();
return implode(array_map('ucfirst', explode('_', __FUNCTION__)));
}
}
FizzBuzz::{'100'}();
解説
- PHPは数字名のメソッド定義はできませんが、数字名のメソッド呼び出しは可能です
-
__callStatic()
はメソッドのオーバーロードと呼ばれるマジックメソッドです - 再帰を停止させるために、ぱっと見でわかりにくい書き方をしてます
- ちなみにPHPにTCO(末尾呼び出し最適化)はありません
私からは以上です。この下は旧作FizzBuzzへのリンクです。
いままでのFizzBuzz
かなりまじめなFizzBuzz
PHP7時代のFizzBuzz
まじめじゃないFizzBuzz
とにかくFizzBuzz