写FizzBu​​zz

Mar*_*tus 22 c# optimization fizzbuzz

阅读编码恐怖,我刚刚遇到了FizzBu​​zz.

原帖是在这里:编码恐怖:为什么程序员不能..程序?

对于那些不知道的人:FizzBu​​zz是一款非常受欢迎的儿童游戏.从1到100计数,每次一个数字可以被3调用"Fizz"整除,每次一个数字可以被5调整为"Buzz",并且每次数字可以被3和5整除时,调用"FizzBu​​zz而不是数

但这一次,我刚刚开始编码.这是一分钟的工作,但有几件我不喜欢的事情.

这是我的代码

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 如何摆脱bool发现?
  2. 有没有比foreach更好的测试方法?

Tho*_*que 181

我认为您的实施不必要地复杂.这个工作做得很好,更容易理解:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案.Fizzbuzz不是为了让它变得更干净而进行复杂化的地方.如果有人觉得需要在FizzBu​​zz中引入复杂性,我不会让他们接触生产代码. (48认同)
  • @MareInfinitus我真的认为你错过了原始问题的背景.在这种情况下,我同意KISS,因为这个问题很少提出要求.您应该只执行完成任务所需的内容. (9认同)
  • @MareInfinitus,你的版本也使用魔法数字和魔法字符串,它们只是在其他地方宣布......你应该遵守KISS原则;) (7认同)
  • 如果他们在适当的地方宣布,那就没有魔力.并且数字和字符串在代码之外被绑定在一起.然后引入另一个数字/密钥对是非问题的.它只是添加了另一个数字/密钥对,没有更多,没有魔法. (6认同)
  • @ema,呃?OCP是OO原则; 这个程序甚至不是面向对象的,它如何违反OCP? (2认同)
  • @ema,在我看来它一直与面向对象的编程有关([维基百科文章](http://en.wikipedia.org/wiki/Open/closed_principle)似乎同意),但我可能错了.无论如何,我写这个代码以最简单的方式解决问题; 我甚至没有尝试让它可扩展... (2认同)
  • @RicardoSanchez我知道这是一个古老的主题,但只是为了对任何偶然发现这个并且对你的问题感到好奇的人添加评论......我不会添加像这样的fizzBu​​zz.如果必须的话,我会添加bool fizzBu​​zz = fizz && buzz; 原因是你没有复制计算的"逻辑"(DRY).但是,我认为拥有一个fizzBu​​zz变量是不必要的,目前的答案已经足够了.如果我要挑剔,我所做的唯一改变就是将逻辑与输出分开......但这是挑剔的,给定的答案是有效的! (2认同)

Mik*_*keP 24

利用条件格式说明符来获得一个漂亮的高尔夫版本:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 不要试图粗鲁但是......可读性对我很重要 (32认同)
  • 这应该给面试官留下深刻印象吗?即使他会挠挠脑袋.易于阅读和维护代码非常重要. (8认同)
  • 几年后可以用字符串插值进一步打高尔夫球:`$"{(i%3*i%5 == 0?0:i):#;} {i%3 :;; Fizz} {i%5: ;;巴兹}"` (6认同)
  • @SageMage 针对简单问题的代码高尔夫挑战可以让您更好地理解语法。 (2认同)

Wug*_*Wug 23

展开以获得最高效率.这个程序可以超越所有其他人.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 重在这里欢笑!+1(顺便说一句,我认为C#编译器会优化它到已展开的版本) (4认同)
  • 请注意,这个不会停在100. (4认同)

Hog*_*gan 19

第3编辑:

这是从你的版本中"摆脱bool"的一种方法(用你的原始问题替换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);
}
Run Code Online (Sandbox Code Playgroud)

先前的答案:

对于纯C#解决方案,请查看Keith Thompson的解决方案.

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用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);
  }
}
Run Code Online (Sandbox Code Playgroud)

和疯狂的一行版本:

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())
      ));
    }
}
Run Code Online (Sandbox Code Playgroud)


Rob*_*b H 19

我认为你要完成的是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在实践中,你会传入combinations方法,但我把它包含在内部只是为了简洁.

  • 过分彻底地"解决FizzBu​​zz问题"是一回事.另一种想法是,这会以某种方式使你在面试情况下看起来很好.这是一个有趣的解决方案,但考虑到原始问题的描述,它很复杂. (11认同)
  • @TheBuzzSaw 我同意,我永远不会在采访中给出这个答案,但想想还是很有趣的。现在我们只需要将它挂接到一个包含组合的数据库表中,并设置一个网络服务来传输结果.. (3认同)
  • 加入`combination.Where(c => isMatch(i,c.Item1)).选择(c => c.Item2).DefaultIfEmpty(i.ToString())`你甚至不需要`if`语句 (2认同)

Jas*_*own 13

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这摆脱了bool found,但迫使你做重复评估.它与i % 15 == 0用于FizzBu​​zz认证的其他一些答案略有不同.这是否更好是有争议的.但是,这是一种不同的方式.

  • 我喜欢创作使用换行符来打印"FizzBu​​zz"......聪明! (2认同)

she*_*nku 11

有人做过这个吗?

Enumerable.Range(1, 100).Select(x =>
                (x % 15 == 0) ? "FIZZBUZZ"
                : (x % 5 == 0) ? "BUZZ"
                : (x % 3 == 0) ? "FIZZ"
                : x.ToString()
                )
                .ToList()
                .ForEach(console.WriteLine);
Run Code Online (Sandbox Code Playgroud)


Pom*_*utZ 8

Linq将为我的解决方案增加5美分.每个人都在使用Select,这基本上是Map功能.恕我直言foldl功能适合更好地解决这个测验:

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());
Run Code Online (Sandbox Code Playgroud)


Xel*_*ela 8

LINQ:

Enumerable.Range(1, 100).ToList().ForEach(i => Console.WriteLine( i % 3 * i % 5 == 0 ? (i % 3 == 0 ? "Fizz" : "") + (i % 5 == 0 ? "Buzz" : "") : i.ToString()));
Run Code Online (Sandbox Code Playgroud)


Shi*_*ala 7

我想你是从一个复杂的方式开始的.改进代码会更复杂.您可以使用temp变量在FizzBu​​zz检查结束时跟踪和显示该变量.下面是代码,您还可以观看此详细信息c#FizzBu​​zz youtube video(http://www.youtube.com/watch?v=OX5TM3q-JQg),其中介绍了如何实施以下代码.

    for (int j = 1; j <= 100; j++)
    {
    string Output = "";

    if (j % 3 == 0) Output = "Fizz";// Divisible by 3 --> Fizz

    if (j % 5 == 0) Output += "Buzz"; // Divisible by 5 --> Buzz

    if (Output == "") Output = j.ToString(); // If none then --> number

    Console.WriteLine(Output); // Finally print the complete output
    }
Run Code Online (Sandbox Code Playgroud)

  • 迄今为止最好的解决方案:) (2认同)