LoginSignup
15
6

More than 5 years have passed since last update.

PHPのFizzBuzz集

Last updated at Posted at 2018-11-13

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

15
6
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6