情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

FizzBuzz問題

FizzBuzz問題

1から100までの数を表示するプログラムを書け。

ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。

[解1]普通の方法

至って普通の方法です。

static void Main(string[] args)
{
    for (int i = 1; i <= 100; i++)
        if (i % 3 == 0 && i % 5 == 0)
            Console.WriteLine("FizzBuzz");
        else if (i % 3 == 0)
            Console.WriteLine("Fizz");
        else if (i % 5 == 0)
            Console.WriteLine("Buzz");
        else
            Console.WriteLine(i);

    Console.ReadLine();
}

[解2] 倍数判定法(Mathクラスで数学的に)

次は、%演算子を使わないでやってみます。

倍数判定法を使います。

ちなみに、倍数判定法には次のようなものがあります。

2の倍数…1の位が2で割り切れる数。

3の倍数…全ての位の合計が3で割り切れる。

5の倍数…1の位が5で割り切れる。

7の倍数…次のいずれかの結果が7で割り切れる数。

     1.下から2桁ずつ順に、1倍、2倍、4倍、…にし、結果を足し合わせる。

     2.下から1桁ずつ順に、1倍、3倍、2倍、-1倍、-3倍、-2倍、…にし、結果を足し合わせる。

     3.下から3桁ずつ順に、奇数番目は足して偶数番目は引く。

11の倍数…次のいずれかの結果が11で割り切れる数。

     1.下の位から奇数番目は足して偶数番目は引く。

     2.下から2桁ずつ足していく。

13の倍数…次のいずれかの結果が13で割り切れる数。

     1.下から1桁ずつ順に、1倍、-3倍、-4倍、-1倍、3倍、4倍、…にし、結果を足し合わせる。

     2.下から3桁ずつ順に、奇数番目は足して偶数番目は引く。

static void Main(string[] args)
{
    for (int i = 1; i <= 100; i++)
        if (Is3NoBaisu(i) && Is5NoBaisu(i))
            Console.WriteLine("FizzBuzz");
        else if (Is3NoBaisu(i))
            Console.WriteLine("Fizz");
        else if (Is5NoBaisu(i))
            Console.WriteLine("Buzz");
        else
            Console.WriteLine(i);

    Console.ReadLine();
}

static bool Is3NoBaisu(int n)
{
    int keta = (int)Math.Log10(n) + 1;
    int kakuketaNoWa = 0;

    for (int i = 0; i < keta; i++)
    {
        kakuketaNoWa += ItiNoKurai(n);
        n /= 10;
    }

    if (kakuketaNoWa >= 10)
        return Is3NoBaisu(kakuketaNoWa);
    else
        return kakuketaNoWa == 3 || kakuketaNoWa == 6 || kakuketaNoWa == 9;
}

static bool Is5NoBaisu(int n)
{
    int itiNoKurai = ItiNoKurai(n);
    return itiNoKurai == 0 || itiNoKurai == 5;
}

static int ItiNoKurai(int n)
{
    int keta = (int)Math.Log10(n) + 1;

    for (int i = keta; i > 1; i--)
    {
        int ZyuNoNZyou = (int)Math.Pow(10, i - 1);
        while (n >= ZyuNoNZyou)
            n -= ZyuNoNZyou;
    }

    return n;
}

[解3]倍数判定法(文字列変換で直観的に)

文字列変換を使ってより分かりやすく解きます。

static void Main(string[] args)
{
    for (int i = 1; i <= 100; i++)
        if (Is3NoBaisu2(i) && Is5NoBaisu2(i))
            Console.WriteLine("FizzBuzz");
        else if (Is3NoBaisu2(i))
            Console.WriteLine("Fizz");
        else if (Is5NoBaisu2(i))
            Console.WriteLine("Buzz");
        else
            Console.WriteLine(i);

    Console.ReadLine();
}

static bool Is3NoBaisu2(int n)
{
    string ns = n.ToString();
    int kakuketaNoWa = 0;

    foreach (char c in ns)
        kakuketaNoWa += int.Parse(c.ToString());

    if (kakuketaNoWa >= 10)
        return Is3NoBaisu2(kakuketaNoWa);
    else
        return kakuketaNoWa == 3 || kakuketaNoWa == 6 || kakuketaNoWa == 9;
}

static bool Is5NoBaisu2(int n)
{
    string ns = n.ToString();
    int itiNoKurai = int.Parse(ns[ns.Length - 1].ToString());
    return itiNoKurai == 0 || itiNoKurai == 5;
}

[解4]最大公約数

自然数nが自然数mで割り切れるならば、nとmの最大公約数は、mであるはずです。

考え方の違いだけで、やっていることは余りを計算するのと変わりありません。

寧ろ、公約数を求める部分で1から順に余りを計算していくので、かなり非効率です。

メリットはありませんが、こんな方法もあるということで。

static void Main(string[] args)
{
    for (int i = 1; i <= 100; i++)
        if (Is3NoBaisu3(i) && Is5NoBaisu3(i))
            Console.WriteLine("FizzBuzz");
        else if (Is3NoBaisu3(i))
            Console.WriteLine("Fizz");
        else if (Is5NoBaisu3(i))
            Console.WriteLine("Buzz");
        else
            Console.WriteLine(i);

    Console.ReadLine();
}

static bool Is3NoBaisu3(int n)
{
    return Gcd(3, n) == 3;
}

static bool Is5NoBaisu3(int n)
{
    return Gcd(5, n) == 5;
}

public static int Gcd(params int[] n)
{
    int gcd = 1;
    for (int i = 2; i <= n.Min(); i++)
    {
        var q1 = from j in n select j % i == 0;
        if (q1.All(x => x))
            gcd = i;
    }
    return gcd;
}

[おまけ]拡張メソッド版

class Program
{
    static void Main(string[] args)
    {
        foreach (var x in 100.FizzBuzz())
            Console.WriteLine(x);

        Console.ReadLine();
    }
}

public static class Extension
{
    public static IEnumerable<string> FizzBuzz(this int _i)
    {
        foreach (int i in Enumerable.Range(1, _i))
            yield return i % 3 == 0 && i % 5 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i.ToString();
    }
}
pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-C#