PHP

PHPのFizzBuzz集


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");

php で短い FizzBuzz を書いてみました - Qiita