写FizzBu​​zz

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

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

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

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

这是我的代码

public void DoFizzBuzz() { var combinations = new Tuple[] { new Tuple (3, "Fizz"), new Tuple (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. 如何摆脱bool发现?
  2. 有没有比foreach更好的测试方法?

我认为你要完成的是FizzBu​​zz的通用解决方案,它适用于任意数量的数字组合。

你有一个良好的开端 – 我想我可以用这个例子回答你的问题:

 public void DoFizzBuzz() { var combinations = new List> { new Tuple (3, "Fizz"), new Tuple (5, "Buzz"), }; Func 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传递给方法,但我将其包含在内部只是为了简洁。

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

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

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

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

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

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

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

先前的答案:

对于纯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); } } } } 

我使用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); } } 

和疯狂的一行版本:

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

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

有人做过这个吗?

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

我想你是从一个复杂的方式开始的。 改进代码会更复杂。 您可以使用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 } 

将为Linq增加5美分的解决方案。 每个人都在使用Select,这基本上是Mapfunction。 恕我直言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()); 

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

好的,到底是什么,这是我喜欢的解决方案:)

 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”案例不再是特殊情况,而是通过代码路径自然发生的事情。

最后,无论什么时候出现,我最喜欢这个问题的是我们可以看到ppl可以提出多少种不同的解决方案。

您可能希望使其可配置,但问题是应该配置什么 – 我们不知道。 也许我们应该对所有循环进行配置(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”,对于这个修改,@ TosmasLevesque的解决方案更好,因为它更容易改变。

不是最有效的,但这里是使用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())}"); } } 

随着Rob H和Jacob Krall的输入,这就是我现在所拥有的。 也许我将来会玩这个…只是想提供它。

 public void DoFizzBuzz() { // expect this to come in as parameter var combinations = new Tuple[] { new Tuple (3, "Fizz"), new Tuple (5, "Buzz"), }; Func 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(i, i.ToString())).Aggregate((v, w) => new Tuple(v.Item1, v.Item2 + w.Item2)).Item2; Console.WriteLine(matchingCombs); } } 

在我看来,FizzBu​​zz问题始终是对外部人员的挑战,使FizzBu​​zz这个词出现而不明确地打印它。 这是我在C#中的解决方案。

 internal void PrintFizzBuzzAlternative(int num) { if (num % 5 == 0) Console.Write("Fizz"); if (num % 3 == 0) Console.Write("Buzz"); if (num % 5 != 0 && num % 3 != 0) Console.Write(num); Console.WriteLine(); } 

function性方法……

 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()))))); 
 Enumerable.Range(1, 100).ToList().ForEach(i=>Console.WriteLine($"{(i%3*i%5==0?0:i):#;}{i%3:;;Fizz}{i%5:;;Buzz}")); 

这个答案全是:

  • LINQ
  • 条件格式
  • 字符串插值
  • 一切都在一条线上

胜利!

使用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+""); 

Linq解决方案很像csells(没有字符串插值)并且适合一行:

 Enumerable.Range(1,100).ToList().ForEach(x=>Console.WriteLine(x%3==0?"Fizz"+(x%5==0?"Buzz":""):x%5==0?"Buzz":x+"")); 

即使已经写了20种其他解决方案,我也会添加它:它就像这样….

 var x = 1; while (x <= 100) { if (x % 3 == 0 && x % 5 == 0) {Console.Writeline("FizzBuzz");} else if (x % 3 == 0) {Console.Writeline("fizz");} else if (x % 5 == 0) {Console.Writeline("Buzz");} else {Console.Writeline(x);} x++ } 

我提出了第一个解决方案。 简单到位,完成工作。 不需要布尔。

我建议在for循环中使用++ i而不是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); } } 

FizzBu​​zz问题是一个很棒的面试问题。 我们已经开始在面试过程中使用它。 令人震惊的是,有多少人无法解决这么简单的问题。

请记住,最初的博客文章最终被锁定,因为大量的人发布了更多的解决方案。 哈哈哈。

无论如何,这是我的C ++! ^ _ ^

 #include  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; } 

最初的问题是:1。如何摆脱找到的布尔? 2.有比foreach更好的测试方法吗?

这摆脱了bool和foreach,我认为它仍然可读。

 public static void DoFizzBuzz() { var combinations = new Tuple[] { new Tuple (3, "Fizz"), new Tuple (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); } } 

一个简单的儿童游戏让我们变得如此兴奋? 🙂

我会建议这个紧凑的代码作为以前简单和漂亮版本的补充。

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

我是初学者,这是我的尝试:

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

我的方法有什么问题吗? 我看起来比其他人的方法简单得多,所以一定是错的。

你可以使用它,只使用你想要的数量

 static void Main(string[] args) { GetFizzBuzz().Take(100).ToList().ForEach(Console.WriteLine); } private static IEnumerable 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); 

我试图解决这个问题而不看答案。 我花了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"); } } } } 

显然这有点超出了FizzBu​​zz挑战的精神。 但在我的基准测试中,这是我在单线程时仍能以最快的速度完成它并且仍然以100结尾。它是半展开并使用StringBuilder 。 它比标准方法快约三倍。

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

没有条件,只有一个三元运算符。

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

null-coalescing运算符非常有用:

 string output = null; for (int i = 1; i <= 100; i++) { if (i % 3 == 0) output += "fizz"; if (i % 5 == 0) output += "buzz"; Console.WriteLine(output ?? i.ToString()); output = null; } Console.ReadKey(); 

不使用任何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)]); }