Writing FizzBuzz

2019-01-30 04:40发布

Reading the coding horror, I just came across the FizzBuzz another time.

The original post is here: Coding Horror: Why Can't Programmers.. Program?

For those who do not know: FizzBuzz is a quite popular childrens game. Counting from 1 to 100, and every time a number is divisible by 3 calling "Fizz", every time a number is divisible by 5 calling "Buzz" and every time a number is divisible by 3 and 5, calling "FizzBuzz instead of the number

But this time, I just started to code it down. It was a job of a minute, but there are several things that I do not like.

Here is my code

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);
    }
}

So my questions are:

  1. How to get rid of the bool found?
  2. Is there a better way of testing than the foreach?

30条回答
仙女界的扛把子
2楼-- · 2019-01-30 04:43

Not the most efficient, but here's one using C#-6 string interpolation:

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())}");
    }
}
查看更多
地球回转人心会变
3楼-- · 2019-01-30 04:43

Relatively simple solution using a for loop.

No Linq or anything - just basic shorthand if statements

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

The Linq solution which is a lot like csells (sans string interpolation) and fits on one line would be:

Enumerable.Range(1,100).ToList().ForEach(x=>Console.WriteLine(x%3==0?"Fizz"+(x%5==0?"Buzz":""):x%5==0?"Buzz":x+""));
查看更多
Deceive 欺骗
4楼-- · 2019-01-30 04:43

The FizzBuzz question is a great interview question. We have started using it in our interview process. It is astounding how many people cannot solve such a simple problem.

Keep in mind, the original blog post was eventually locked due to a flood of people posting more solutions. Hahaha.

Regardless, here is mine in 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;
}
查看更多
神经病院院长
5楼-- · 2019-01-30 04:45

You can use either use this and only take the amount you want

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);
    }
}

Or simply use this :

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);
查看更多
一纸荒年 Trace。
6楼-- · 2019-01-30 04:46

You want probably make it configurable, but the question is what should be made configurable - we don't know that. Maybe we should make configurable all the cycle (FizzBuzz has the cycle). Here is very small and fun version with configurable cycle:

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);

So if the strings or whole cycle should be changed it is easy to change. But you just don't know what to make configurable. Maybe condition will change: "for prime numbers print Pizz" and for this modification the solution by @ThomasLevesque is better, because it is easier to change.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-01-30 04:48

Will add my 5 cents to solution by Linq. Everybody is using Select, which is basically Map function. IMHO foldl function suits better to solve this quiz:

Console.WriteLine(
                Enumerable
                .Range(1, 100)
                .Aggregate(new StringBuilder(), (builder, i)
                    => i % 15 == 0 ? builder.AppendLine("FizzBuzz")
                     : i % 3 == 0 ? builder.AppendLine("Fizz")
                     : i % 5 == 0 ? builder.AppendLine("Buzz")
                     : builder.AppendLine(i.ToString()))
                .ToString());
查看更多
登录 后发表回答