C#でFizzBuzzを実装する

FizzBuzzの問題の解法は出尽くしていると思いますが、自分でコードを書いた事が無かったためチャレンジしてみようと思います。

作成環境はVS2017(15.7.2) + .NET4.7.2 (≒C#7.2)です。

ルール確認と模範解答

まずはルールの確認です。概ね以下の通りです。

  • 最初は1から自然数でインクリメント
  • 3の倍数で"Fizz"を出力
  • 5の倍数で"Buzz"を出力
  • 3と5の公倍数は"FizzBuzz"を出力

模範回答ですが、素直に書くと以下のようになります。

// 模範回答
public static void Main(string[] args)
{
    for (int i = 1; i <= 100; i++)
    {
        if (i % 15 == 0)
        {
            Console.WriteLine("FizzBuzz");
        }
        else if (i % 5 == 0)
        {
            Console.WriteLine("Buzz");
        }
        else if (i % 3 == 0)
        {
            Console.WriteLine("Fizz");
        }
        else
        {
            Console.WriteLine(i);
        }
    }
}

少し短くFizzBuzz記述する

ここからは自分で考えてみました。

競技大会的な黒魔術は無理なので、ほどほどなコードを書いてみたいと思います。

基本的に、出力があってればOKの精神です。

考え方のポイント、以下の通りです。

public static void Main(string[] args)
{
    for (int i = 0; i++ < 100;)
    {
        // (1) 公倍数は計算しない。FizzとBuzzが連続で出ればFizzBuzz
        // (2) Console.WriteLineを何回も書きたくないので先に出力を決定する
        // (3) 文字が無ければ数字とする
        string str = (i % 3 == 0 ? "Fizz" : "") + (i % 5 == 0 ? "Buzz" : "");
        Console.WriteLine(str == "" ? $"{i}" : str);
    }
}
// [出力]
// 1
// 2
// Fizz
// 4
// Buzz
// Fizz
// 7
// 8

また、おしゃれ感を出すためにfor文を拡張メソッドに変えると全体の雰囲気が明るくなります(謎

おしゃれ感を優先(投げやり)のあまり前述のより長いですし、計算量は通常の倍です(;^ω^)

public static void Main(string[] args)
{
    // お洒落感のあるコード
    string f (int i ) { return (i % 3 == 0 ? "Fizz" : "") + (i % 5 == 0 ? "Buzz" : ""); }
    Enumerable.Range(1, 100).ToList().ForEach(i => Console.WriteLine(f(i) == "" ? $"{i}" : f(i)));
    
    // fはデリゲートでもOK
    //Func<int, string> f = i => (i % 3 == 0 ? "Fizz" : "") + (i % 5 == 0 ? "Buzz" : "");
}

ちなみにforの代わりにForEachは通常パフォーマンスが悪いので使用はNGです。計測したら4割くらい遅かったです。(リストへの一括処理とかで可読性優先なら良いと思いますが。

最新の企画を使ってFizzBuzz

最後のお洒落感を流用してC#7.3のタプル同士の比較という最新規格を使ってFizzBuzzしてみようと思います。

タプルの中身が空だったら数字を出しています。

以下のコードコンパイルするには、プロジェクトからC#7.3の有効化とNuGetからValueTypleを参照に追加します。

// C#7.0のローカル関数、C#7.3のタプルの比較を使ったコード
(object, object) f(int n) => (n % 3 == 0 ? "Fizz" : "", n % 5 == 0 ? "Buzz" : "");
for (int i = 0; i++ < 100;)
{
    Console.WriteLine(f(i) == ("", "") ? $"{i}" : $"{f(i)}".Replace(", ", "").Trim('(', ')'));
}

以上です。