25

コーディングの恐怖を読んで、私はちょうど別の時にFizzBu​​zzに出くわしました。

元の投稿はここにあります:コーディングホラー:なぜプログラマーは..プログラムできないのですか?

知らない人のために:FizzBu​​zzは非常に人気のある子供向けゲームです。1から100まで数えて、数値が3で割り切れるたびに文字列「Fizz」が呼び出され、数値が5で割り切れるたびに文字列「Buzz」が呼び出され、数値が3と5で割り切れるたびに両方数字の代わりに「FizzBu​​zz」という文字列が一緒に呼び出されます。

今回はコードを書いて1分かかりましたが、気に入らないことがいくつかあります。

これが私のコードです:

public void DoFizzBuzz()
{
    var combinations = new Tuple<int, string>[] 
    { 
        new Tuple<int, string> (3, "Fizz"), 
        new Tuple<int, string> (5, "Buzz"), 
    };

    for (int i = 1; i <= 100; ++i)
    {
        bool found = false;

        foreach (var comb in combinations)
        {
            if (i % comb.Item1 == 0)
            {
                found = true;
                Console.Write(comb.Item2);
            }
        }

        if (!found)
        {
            Console.Write(i);
        }

        Console.Write(Environment.NewLine);
    }
}

だから私の質問は:

  1. 見つかったブール値を取り除くにはどうすればよいですか?
  2. foreachよりも優れたテスト方法はありますか?
4

43 に答える 43

195

あなたの実装は不必要に複雑だと思います。これは仕事をし、理解しやすいです:

public void DoFizzBuzz()
{
    for (int i = 1; i <= 100; i++)
    {
        bool fizz = i % 3 == 0;
        bool buzz = i % 5 == 0;
        if (fizz && buzz)
            Console.WriteLine ("FizzBuzz");
        else if (fizz)
            Console.WriteLine ("Fizz");
        else if (buzz)
            Console.WriteLine ("Buzz");
        else
            Console.WriteLine (i);
    }
}
于 2012-08-01T17:39:21.567 に答える
27

条件付き書式指定子を利用して、洗練されたバージョンを取得します。

public void DoFizzBuzz()
{
    for(int i=1;i<101;i++)Console.WriteLine("{0:#;}{1:;;Fizz}{2:;;Buzz}",i%3*i%5==0?0:i,i%3,i%5);
}
于 2012-08-01T17:57:20.010 に答える
26

最大限の効率を得るために広げます。このプログラムは、他のすべてを打ち負かすことができます。

public void FizzBuzz()
{
    const string FIZZ = "Fizz";
    const string BUZZ = "Buzz";
    const string FIZZBUZZ = "FizzBuzz";

    int i = 0;
    while (i < 150)
    {
        Console.WriteLine(++i);
        Console.WriteLine(++i);
        Console.WriteLine(FIZZ); ++i;
        Console.WriteLine(++i);
        Console.WriteLine(BUZZ); ++i;
        Console.WriteLine(FIZZ); ++i;
        Console.WriteLine(++i);
        Console.WriteLine(++i);
        Console.WriteLine(FIZZ); ++i;
        Console.WriteLine(BUZZ); ++i;
        Console.WriteLine(++i);
        Console.WriteLine(FIZZ); ++i;
        Console.WriteLine(++i);
        Console.WriteLine(++i);
        Console.WriteLine(FIZZBUZZ); ++i;
    }
}
于 2012-08-01T18:12:53.277 に答える
22

あなたが達成しようとしているのは、FizzBu​​zz の一般的なソリューションであり、任意の数の単語の組み合わせで機能すると思います。

あなたは良いスタートを切っています - 私はこの例であなたの質問に答えることができると思います:

public void DoFizzBuzz()
{
    var combinations = new List<Tuple<int, string>>
    { 
        new Tuple<int, string> (3, "Fizz"), 
        new Tuple<int, string> (5, "Buzz"), 
    };

    Func<int, int, bool> isMatch = (i, comb) => i % comb == 0;
    for (int i = 1; i <= 100; i++)
    {
        Console.Write(i);

        var matchingCombs = combinations.Where(c => isMatch(i, c.Item1)).ToList();
        if (matchingCombs.Any())
        {
            Console.Write(string.Join("", matchingCombs.Select(c => c.Item2)));
        }
        else
        {
            Console.Write(i);
        }
        Console.Write(Environment.NewLine);
    }
}

実際には、メソッドに渡しますがcombinations、簡潔にするために内部に含めました。

于 2012-08-01T18:08:51.140 に答える
20

3番目の編集:

これがあなたのバージョンから「ブール値を取り除く」ための1つの方法です(つまり、元の質問のforループをこれに置き換えます):

for (int i = 1; i <= 100; i++)
{
  var x = combinations.Where(n => i % n.Item1 == 0);

  if (x.Count() == 0)
    Console.Write(i);
  else
    Console.Write(string.Join("",x.Select(e => e.Item2)));

  Console.Write(Environment.NewLine);
}

以前の回答:

純粋なC#ソリューションについては、KeithThompsonソリューションを確認してください。

using System;
class FizzBuzz {
    static void Main() {
        for (int n = 1; n <= 100; n ++) {
            if (n % 15 == 0) {
                Console.WriteLine("FizzBuzz");
            }
            else if (n % 3 == 0) {
                Console.WriteLine("Fizz");
            }
            else if (n % 5 == 0) {
                Console.WriteLine("Buzz");
            }
            else {
                Console.WriteLine(n);
            }
        }
    }
}

linqを使用してFixBuzzに少し取り組みました。これらは私が思いついた解決策です-Linqを使用してこの問題の解決策を表現するための最良の方法を表していると思います。(GitHub

using System;
using System.Linq;

class FizzBuzz {
  static void Main() {
    var list = Enumerable.Range(1,100)
                .Select(n => {
                      if (n % 15 == 0) {
                        return "FizzBuzz";
                      }
                      if (n % 3 == 0) {
                        return "Fizz";
                      }
                      if (n % 5 == 0) {
                        return "Buzz";
                      }
                      return n.ToString();
                    });

    foreach(string item in list)
      Console.WriteLine(item);
  }
}

そしてクレイジーな1行バージョン:

using System;
using System.Linq;

class FizzBuzz {
    static void Main() {
      Console.WriteLine(
      String.Join(
        Environment.NewLine,
        Enumerable.Range(1, 100)
          .Select(n => n % 15 == 0 ? "FizzBuzz" 
                     : n % 3 == 0 ? "Fizz" 
                     : n % 5 == 0 ? "Buzz" 
                     : n.ToString())
      ));
    }
}
于 2012-08-01T17:36:42.113 に答える
15
public void DoFizzBuzz()
{
    for (int i = 1; i <= 100; i++)
    {
        if (i % 3 == 0)
            Console.Write("Fizz");
        if (i % 5 == 0)
            Console.Write("Buzz");
        if (!(i % 3 == 0 || i % 5 == 0))
            Console.Write(i);

        Console.Write(Environment.NewLine);
    }
}

これにより bool が取り除かfoundれますが、重複した評価を行う必要があります。i % 15 == 0FizzBu​​zz 資格に使用する他のいくつかの回答とは少し異なります。これが良いかどうかは議論の余地があります。しかし、それはの方法です。

于 2012-08-01T17:52:29.297 に答える
13

誰かがすでにこれをしましたか?

Enumerable.Range(1, 100).Select(x =>
                (x % 15 == 0) ? "FIZZBUZZ"
                : (x % 5 == 0) ? "BUZZ"
                : (x % 3 == 0) ? "FIZZ"
                : x.ToString()
                )
                .ToList()
                .ForEach(console.WriteLine);
于 2013-11-27T22:21:53.003 に答える
4

最も効率的ではありませんが、C#-6文字列補間を使用したものを次に示します。

void Main()
{
    for (int i = 1; i <= 100; i++)
    {
       Console.WriteLine($"{(i % 15 == 0 ? "FizzBuzz" : 
                             i % 3 == 0 ? "Fizz" : 
                             i % 5 == 0 ? "Buzz" : i.ToString())}");
    }
}
于 2015-11-23T13:30:39.143 に答える
4
Enumerable.Range(1, 100).ToList().ForEach(i=>Console.WriteLine($"{(i%3*i%5==0?0:i):#;}{i%3:;;Fizz}{i%5:;;Buzz}"));

この答えにはすべてがあります:

  • リンク
  • 条件付き書式
  • 文字列補間
  • すべて 1 行で

勝利!

于 2016-09-02T13:16:12.037 に答える
3

答えを見ずにこの問題を解こうとしました。成功するのに3時間かかりました。(ちなみに、私は単なる趣味のプログラマーですので、私を激しく非難しないでください:)) これは私のC#バージョンのソリューションです:

        static void Main(string[] args)
    {

        for (int i = 1; i <= 100; i++)
        {
            if(  ((i % 3) != 0) && ((i % 5) != 0))
            {
                WriteLine($"{i}");
            }
            else
            {
                if ((i % 15) == 0)
                {
                    WriteLine("FizzBuzz");
                }
                else if ((i % 3) == 0)
                {
                    WriteLine("Fizz");
                }
                else if ((i % 5) == 0)
                {
                    WriteLine("Buzz");
                }
            }                 
        }
    }
于 2016-07-10T18:45:52.183 に答える
3

FizzBu​​zz の質問は、優れた面接の質問です。面接プロセスで使用し始めました。このような単純な問題を解決できない人がいかに多いかは驚くべきことです。

元のブログ投稿は、他のソリューションを投稿する人が殺到したため、最終的にロックされたことを覚えておいてください. ハハハ。

いずれにせよ、これは私の C++ です。^_^

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
    for (int i = 1; i <= 100; ++i)
    {
        bool isMultipleOfThree = (i % 3) == 0;
        bool isMultipleOfFive = (i % 5) == 0;

        if (isMultipleOfThree) cout << "Fizz";
        if (isMultipleOfFive) cout << "Buzz";
        if (!isMultipleOfThree && !isMultipleOfFive) cout << i;

        cout << '\n';
    }

    return 0;
}
于 2012-08-01T18:05:03.383 に答える
3

私は初心者です、ここに私の試みがあります:

public void DoFizzBuzz()
   {
       for (int i = 1; i < 101; i++)
       {

           if ((i % 3 == 0) && (i % 5 == 0))
           {
               Console.WriteLine("{0} FizzBuzz", i);
           }
           else if (i % 3 == 0)
           {
               Console.WriteLine("{0} Fizz", i);
           }
           else if (i % 5 == 0)
           {
               Console.WriteLine("{0} Buzz", i);
           }
           else
           {
               Console.WriteLine(i);
           }

       }
       Console.ReadLine();
   }

私のアプローチに何か問題がありますか?私のアプローチは他の人のアプローチよりもはるかに単純に見えるので、間違っているに違いありません。

于 2013-02-13T05:10:38.053 に答える
3

わかりました、一体、これが私が好きになった解決策です:)

public void DoFizzBuzz()
{
    for (int i = 1; i <= 100; ++i)
    {
        bool isDivisibleByThree = i % 3 == 0;
        bool isDivisibleByFive = i % 5 == 0;

        if (isDivisibleByThree || isDivisibleByFive)
        {
            if (isDivisibleByThree)
                cout << "Fizz";

            if (isDivisibleByFive)
                cout << "Buzz";
        }
        else
        {
            cout << i;
        }
        cout << endl;
    }
}

明らかに、これは最速の解決策ではありませんが、読みやすさを強調し、「FizzBu​​zz」のケースを特別なケースではなく、コード パスを通じて自然に発生するものにするので、私は気に入っています。

結局のところ、この質問が出てくるたびに私が最も気に入っているのは、人々がどれだけ多くの異なる解決策を思い付くことができるかを見ることができるということです.

于 2012-08-01T20:29:17.957 に答える
3

おそらく構成可能にしたいでしょうが、問題は何を構成可能にするかです-それはわかりません。たぶん、すべてのサイクルを構成可能にする必要があります (FizzBu​​zz にはサイクルがあります)。これは、構成可能なサイクルを備えた非常に小さくて楽しいバージョンです。

string[] fizzBuzzCycle = 
    "FizzBuzz,{0},{0},Fizz,{0},Buzz,Fizz,{0},{0},Fizz,Buzz,{0},Fizz,{0},{0}"
    .Split(',');

for (int i = 1; i <= 100; i++)
    Console.WriteLine(fizzBuzzCycle[i%fizzBuzzCycle.Length], i);

したがって、ストリングまたはサイクル全体を変更する必要がある場合は、簡単に変更できます。しかし、何を構成可能にするかがわかりません。条件が変更される可能性があります。「素数の場合は Pizz を出力します」。この変更では、@ThomasLevesque によるソリューションの方が変更しやすいため、より優れています。

于 2013-08-07T11:04:36.670 に答える
2

このコンパクトなコードを、以前のシンプルで優れたバージョンに追加することをお勧めします。

for (int i = 1; i <= 100; i++) // i++ but not ++i as in your example, be careful here
{
    bool fizz = i % 3 == 0;
    bool buzz = i % 5 == 0;
    string output = fizz && buzz ? "FizzBuzz" :
                            fizz ? "Fizz" :
                            buzz ? "Buzz" :
                            i.ToString();

    Console.WriteLn(output);
}
于 2013-01-23T15:38:13.760 に答える
2

機能的なアプローチ...

Console.WriteLine(Enumerable
    .Range(1,100)
    .Aggregate("", 
        (a,i) => a + "\n" + (i%15==0 ? "fizzbuzz" : 
                                (i%5==0 ? "buzz" :
                                    (i%3==0 ? "fizz" : i.ToString())))));
于 2015-12-11T06:20:10.990 に答える
2

Rob H と Jacob Krall の意見により、現時点で私が持っているものを以下に示します。おそらく私は将来それをいじるでしょう...それを提供したかっただけです。

public void DoFizzBuzz()
{
    // expect this to come in as parameter
    var combinations = new Tuple<int, string>[] 
    { 
        new Tuple<int, string> (3, "Fizz"), 
        new Tuple<int, string> (5, "Buzz"), 
    };

    Func<int, int, bool> isMatch = (i, comb) => i % comb == 0;

    // expect the borders 1, 100 to come in as parameters
    for (int i = 1; i <= 100; ++i)
    {
        var matchingCombs = combinations.Where(c => isMatch(i, c.Item1)).DefaultIfEmpty(new Tuple<int, string>(i, i.ToString())).Aggregate((v, w) => new Tuple<int, string>(v.Item1, v.Item2 + w.Item2)).Item2;
        Console.WriteLine(matchingCombs);
    }
}
于 2012-08-01T19:45:50.663 に答える
2

i++ ではコピーを作成する必要があるため、for ループでは i++ の代わりに ++i を使用することをお勧めします;)

public void DoFizzBuzz()
{
    for (int i = 1; i < 101; ++i)
    {
        if (i % 15 == 0)
            Console.WriteLine ("FizzBuzz");
        else if (i % 3 == 0)
            Console.WriteLine ("Fizz");
        else if (i % 5 == 0)
            Console.WriteLine ("Buzz");
        else
            Console.WriteLine (i);
    }
}
于 2012-08-01T17:45:38.557 に答える
2

for ループを使用した比較的単純なソリューション。

Linq などはありません - 基本的な省略形の if ステートメントのみ

for(int x=1;x<101;x++)
    Console.WriteLine(x%3==0?"Fizz"+(x%5==0?"Buzz":""):x%5==0?"Buzz":x+"");

csells (文字列補間なし) によく似ていて、1 行に収まる Linq ソリューションは次のようになります。

Enumerable.Range(1,100).ToList().ForEach(x=>Console.WriteLine(x%3==0?"Fizz"+(x%5==0?"Buzz":""):x%5==0?"Buzz":x+""));
于 2016-09-26T16:04:36.500 に答える
2

明らかに、これは FizzBu​​zz チャレンジの精神から少し外れています。しかし、私のベンチマークでは、これはシングル スレッドでありながら 100 で終了しているときに作成できる最速のものでしたStringBuilder。これは、標準的なアプローチよりも約 3 倍高速です。

const string FIZZ = " Fizz\n";
const string BUZZ = " Buzz\n";
const string FIZZBUZZ = " FizzBuzz\n";
    ...
var sb = new StringBuilder();
int i = 0;

while(true)
{       
    sb.Append(i+3);
    sb.Append(FIZZ);        
    sb.Append(i+5);
    sb.Append(BUZZ);        
    sb.Append(i+6);
    sb.Append(FIZZ);        
    sb.Append(i+9);
    sb.Append(FIZZ);        
    sb.Append(i+10);
    sb.Append(BUZZ);        
    if(i+12 > 100)
        break;
    sb.Append(i+12);
    sb.Append(FIZZ);    
    i+=15;
    sb.Append(i);
    sb.Append(FIZZBUZZ);
}

Console.Write(sb.ToString());
于 2016-10-16T18:16:34.177 に答える
1

これを使用して、必要な量だけ取ることができます

static void Main(string[] args)
{
    GetFizzBuzz().Take(100).ToList().ForEach(Console.WriteLine);
}

private static IEnumerable<string> GetFizzBuzz()
{
    for (var i = 0; i < int.MaxValue; i++)
    {
        if (i % 3 == 0 && i % 5 == 0) yield return "FizzBuzz";
        if (i % 3 == 0) yield return "Fizz";
        yield return i % 5 == 0 ? "Buzz" : i.ToString(CultureInfo.InvariantCulture);
    }
}

または単にこれを使用します:

Enumerable.Range(1, 100).Select(s => {
    if (s % 3 == 0 && s % 5 == 0) return "FizzBuzz";
    if (s % 3 == 0) return "Fizz";
    return s%5 == 0 ? "Buzz" : s.ToString(CultureInfo.InvariantCulture);
}).ToList().ForEach(Console.WriteLine);
于 2013-06-28T17:47:55.303 に答える
1

元の質問は次のとおりです。 1.見つかった bool を取り除く方法は? 2. foreach よりも良いテスト方法はありますか?

これにより bool と foreach が取り除かれ、まだ読みやすいと思います。

public static void DoFizzBuzz()
{
    var combinations = new Tuple<int, string>[]  
    {  
        new Tuple<int, string> (3, "Fizz"),  
        new Tuple<int, string> (5, "Buzz"),  
    };

    for (int i = 1; i <= 100; i++)
    {
        var fb = combinations.Where(t => {
            if (i % t.Item1 == 0)
            {
                Console.Write(t.Item2);
                return true;
            }
            return false;
        }).ToList();

        if (!fb.Any())
        {
            Console.Write(i);
        }

        Console.Write(Environment.NewLine);
    }
} 

シンプルな子供向けゲームでこんなに興奮するなんて誰が思いつくでしょうか? :)

于 2012-08-01T18:15:29.813 に答える
1

if 条件がなく、三項演算子が 1 つだけです。

string[] s = new string[6]{"Fizz", "Buzz", "", "", "", ""};
for (int i = 1; i <= 100; i++)
{
    string output = s[(i%3)*2] + s[(i%5)+1];
    Console.WriteLine(string.IsNullOrEmpty(output)? "" + i : output);
}
于 2017-02-24T20:14:00.667 に答える
0

JavaScript での簡単なソリューション

var i = 1;
while (i <= 100){
    console.log((i % 3 === 0 && i % 5 === 0) ? "FizzBuzz" : (i % 3 === 0) ? "Fizz" : (i % 5 === 0 ? "Buzz" : i));
    i++;
}
于 2016-10-03T18:16:07.997 に答える
0

わかりました - かみます。最近の最初のコーディング インタビューで思いついた LINQ の重いソリューション。この単純な問題に対して、驚くほど多くの異なる解決策があります。

public static class FizzBuzzUtils
{
    private static List<KeyValuePair<int, string>> map = new List<KeyValuePair<int, string>> {
        new KeyValuePair<int, string>(3, "Fizz"),
        new KeyValuePair<int, string>(5, "Buzz")
    };

    public static string GetValue(int i)
    {
        var matches = map.Where(kvp => i % kvp.Key == 0)
            .Select(kvp => kvp.Value)
            .ToArray();
        return matches.Length > 0 ? string.Join(string.Empty, matches) : i.ToString();
    }

    public static IEnumerable<string> Range(int start, int count)
    {
        return Enumerable.Range(start, count)
            .Select(i => GetValue(i));
    }
}
于 2019-04-01T18:00:21.170 に答える
0

一般的な FizzBu​​zz を使用するため (私はこれをRaindropsと呼んでいます)、一般的で読みやすくするためにいくつかの簡単な変更を行います。

  1. 「combinations」の名前を「primeFactors」に変更すると、もう少し説明的になります
  2. タプル フィールドへのアクセスをより読みやすくするためのタプルフィールド名
  3. 必要な表示文字列の素因数のリストを照会するLinqforeach (を削除)
    • Whereリストを現在の整数の因数でフィルタリングします
    • Select一致する要素を表示文字列に変換します
    • DefaultIfEmpty「一致が見つからない」ケースを処理して、そのブール値を削除できるようにします
    • Aggregate一致するすべての表示文字列を連結します

オンラインでお試しください!

public void DoFizzBuzz()
{
    var primeFactors = new (int Factor, string Display)[]
    {
        (3, "Fizz"),
        (5, "Buzz")
    };
    for (var integer = 1; integer <= 100; ++integer)
        Console.WriteLine(primeFactors
            .Where(tuple => integer % tuple.Factor == 0)
            .Select(tuple => tuple.Display)
            .DefaultIfEmpty($"{integer}")
            .Aggregate((first, second) => $"{first}{second}")
        );
}
于 2021-07-15T17:36:13.727 に答える
0

パイソンで……

 for i in range(0, 100) :
        a = i % 3 == 0
        b = i % 5 == 0

        if(a & b):
            print("FizzBuzz")
        elif(a):
            print("Fizz")
        elif(b):
            print("Buzz")
        else:
            print(i)
于 2016-10-07T14:24:34.003 に答える
0

If を使用せずに、C# コードを使用します。

 //False = 0, True = 1.
    private void DivisibilityByFiveThreeTest(int num)
    {
        string[,] values = new string [2,2]{
                             {"None","Fizz"},
                             {"Buzz","FizzBuzz"}
                             };
        for(int i=1;i< num;i++)
        Console.WriteLine(values[Convert.ToInt32(i % 5 == 0), Convert.ToInt32(i%3==0)]);

    }
于 2014-08-18T20:54:29.160 に答える
0

C++ 実装

vector<string> FizzBuzz::execute(int n) {

    if(n == 0)
        return vector<string>();

    auto push = n % 15 == 0 ? "fizzbuzz" :
                n % 3 == 0 ? "fizz" :
                n % 5 == 0 ? "buzz" :
                to_string(n);

    auto execution = execute(n-1);
    execution.push_back(push);
    return execution;
}
于 2017-07-02T16:18:57.447 に答える