PHPで最も短い
<?while($i++<100)echo[Fizz][$i%3].[Buzz][$i%5]?:$i,"
";
PHPでFizzBuzzを書いてみました — A Day in Serenity (Reloaded) — PHP, FuelPHP, Linux or something
再帰呼び出し
つまり、for
,foreach
,while
等のループ構文を使わない。
<?php
function fizzbuzz($i, $max = 100)
{
if ($i % 15 === 0) {
echo 'FizzBuzz', PHP_EOL;
} elseif ($i % 3 === 0) {
echo 'Fizz', PHP_EOL;
} elseif ($i % 5 === 0) {
echo 'Buzz', PHP_EOL;
} else {
echo $i, PHP_EOL;
}
if ($i < $max) {
fizzbuzz($i + 1, $max);
}
}
fizzbuzz(1);
関数
条件ごとに関数を定義し、たらい回しにするパターン。
<?php
function fizz($i)
{
return $i % 3 ? null : 'Fizz';
}
function buzz($i)
{
return $i % 5 ? null : 'Buzz';
}
function fizzbuzz($i)
{
return $i % 15 ? null : 'FizzBuzz';
}
for ($i = 1; $i <= 100; $i ++) {
echo fizzbuzz($i) ?? fizz($i) ?? buzz($i) ?? $i, PHP_EOL;
}
条件分岐(if等)を使わないFizzBuzz
配列操作だけで実現するアプローチ。
<?php
$fizz = array_fill_keys(range(0, 100, 3), 'Fizz');
// -> [0 => "Fizz", 3 => "Fizz", 6 => "Fizz", 9 => "Fizz", ...]
$buzz = array_fill_keys(range(0, 100, 5), 'Buzz');
// -> [0 => "Buzz", 5 => "Buzz", 10 => "Buzz", 15 => "Buzz", ...]
$fizzbuzz = array_fill_keys(range(0, 100, 15), 'FizzBuzz');
// -> [0 => "FizzBuzz", 15 => "FizzBuzz", 30 => "FizzBuzz", 45 => "FizzBuzz", ...]
$numbers = range(0, 100);
// -> [0 => 0, 1 => 1, 2 => 2, 3 => 3, ...]
$result = array_replace($numbers, $fizz, $buzz, $fizzbuzz);
// -> [0 => "FizzBuzz", 1 => 1, 2 => 2, 3 => "Fizz", ...]
unset($result[0]);
echo implode("\n", $result);
ジェネレーター
yield
を使っての実現も可能。
<?php
function fizzbuzz($max = 100)
{
for ($i = 1; $i <= $max; $i ++) {
if ($i % 15 === 0) {
yield 'FizzBuzz';
} elseif ($i % 3 === 0) {
yield 'Fizz';
} elseif ($i % 5 === 0) {
yield 'Buzz';
} else {
yield $i;
}
}
}
foreach (fizzbuzz() as $v) {
echo $v, PHP_EOL;
}
Chain of Responsibility パターン
入力を扱える担当オブジェクトに至るまで、担当者をたらい回しにするGoFのデザインパターンであるChain of Responsibityを使って実現する。オブジェクト指向の原則に従っているため、新たなゲームルール(例えば、7で割り切れるときに"Hoge"と返すといったもの)を追加するときに、既存のクラス実装を一切変更しなくても実装できるといった拡張性がある。
<?php
abstract class Handler
{
private $next;
public function __construct(Handler $next)
{
$this->next = $next;
}
final public function handle(int $i): string
{
return $this->canHandle($i) ? $this->respond($i) : $this->next->handle($i);
}
abstract protected function canHandle(int $i): bool;
abstract protected function respond(int $i): string;
}
class FizzHandler extends Handler
{
protected function canHandle(int $i): bool
{
return $i % 3 === 0;
}
protected function respond(int $i): string
{
return 'Fizz';
}
}
class BuzzHandler extends Handler
{
protected function canHandle(int $i): bool
{
return $i % 5 === 0;
}
protected function respond(int $i): string
{
return 'Buzz';
}
}
class FizzBuzzHandler extends Handler
{
protected function canHandle(int $i): bool
{
return $i % 3 === 0 && $i % 5 === 0;
}
protected function respond(int $i): string
{
return 'FizzBuzz';
}
}
class NumberHandler extends Handler
{
public function __construct()
{
}
protected function canHandle(int $i): bool
{
return true;
}
protected function respond(int $i): string
{
return $i;
}
}
$fizzbuzz = new FizzBuzzHandler(new FizzHandler(new BuzzHandler(new NumberHandler)));
foreach (range(1, 100) as $i) {
echo $fizzbuzz->handle($i), PHP_EOL;
}
FizzBuzz Web API
実務ではある要求を実現するために外部システムの力を借りることがある。FizzBuzz問題でもそれが許されるとしたら、FizzBuzzの結果を返すエンドポイントを使う、といった解決策も有り得るかもしれない。
<?php
echo file_get_contents("http://riaf.jp/f");