【PHP】$なしでFizzBuzz問題を解く

  • 2020年12月10日
  • PHP

 PHP の変数名は次の正規表現で記述できます。

^\$[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$

 $ で始まって数字以外の 1 文字が続き、そのあと自由な文字が 0 文字以上続く、というわけです。$ がないとプログラムを書くことが難しい PHP ですが、$ なしでも FizzBuzz 問題を解くことはできます。
 ちなみに FizzBuzz 問題とは次の条件を満たすプログラムを作る問題です。

  • 1から100までの整数を順に出力する
  • 3の倍数のときは数の代わりに”Fizz”を出力する
  • 5の倍数のときは”Buzz”を出力する
  • 3と5の公倍数のときは”Fizz Buzz”を出力する

 例えば、次の様に Fizz, Buzz 文字列を入れ込んだ配列を生成して、文字列化してまとめて出力できます。
Online PHP editor | output for nXRa7

<?php
// const: 定数キーワード。不変の値は $ なしでも格納できます
const START = 1;
const END   = 100;
// implode: 配列要素を文字列により連結する
// @see https://www.php.net/manual/ja/function.implode.php
echo implode("\n", 
    // array_slice: 配列を任意の範囲で切り取る
    // @see https://www.php.net/manual/ja/function.array-slice.php
    array_slice(
        // array_replace: 配列の中身を置き換える
        // @see https://www.php.net/manual/ja/function.array-replace.php
        array_replace(range(0, END), 
            // array_fill_keys: 第二引数の値で埋まった第一引数のキーらを持つ配列を得る
            // @see https://www.php.net/manual/ja/function.array-fill-keys.php
            array_fill_keys(range(0, END, 3), 'Fizz'), 
            array_fill_keys(range(0, END, 5), 'Buzz'),
            array_fill_keys(range(0, END, 15), 'FizzBuzz')
        ),
        START, END
    )
);

 PHP 組み込みの関数は 9000 強個あり(PHP: 関数・メソッド – Manual調べ)、探せば大抵近いなにかしらが出てきます。C 製の PHP 、特に新しい PHP の内部の実行速度は非常に速いです。自前で for や while 等駆使してスクリプトを書くよりも関数を呼び出した方がコードが読みやすくなり、実行速度も速くなります。上記例程でないにせよ関数を駆使すると色々とありがたいことが起きます。

 FizzBuzz 問題ですが、次の様に再帰とバックトレースを用いてループを作ることもできます。
Online PHP editor | output for V9WIE

<?php

const START = 1;
const END   = 100;

/**
 * バックトレースの深さからインデックス相当の値を取得
 * @return int
 */
function getI(): int
{
    // debug_backtrace: バックトレースを配列で生成
    // @see https://www.php.net/manual/ja/function.debug-backtrace.php
    // count: 配列の長さを取得
    // @see https://www.php.net/manual/ja/function.count.php
    return count(debug_backtrace()) - 2 + START;
}

/**
 * 再帰で Fizz, Buzz を echo
 */
function echoFizzBuzz(): void
{
    if (getI() % 15 === 0) {
        echo getI().': FizzBuzz';
    } elseif (getI() % 3 === 0) {
        echo getI().': Fizz';
    } elseif (getI() % 5 === 0) {
        echo getI().': Buzz';
    } else {
        echo getI().': '.getI();
    }
    echo "\n";
    // 再帰で一次変数抜きにループを実現する
    // 再帰でバックトレースを深くしてインデックスを進める
    if (getI() < END) {
        echoFizzBuzz();
    }
}

echoFizzBuzz();

 debug_backtrace は PHP の処理フローを追跡する関数です。プログラムを書いている人がフローを完全に把握している前提になりますし、そんなことをしなくてもよいならば絶対にすべきでないですが、debug_backtrace の中身を元に処理を制御することで通常の PHP の世界では困難なメタ的な処理を作ることができます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG