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 の拡張メソッドは処理速度が少し遅めなので高頻度に実行される場所での使用は避けましょう(計測したら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('(', ')'));
}

以上です。