Написание FizzBuzz - программирование
Подтвердить что ты не робот

Написание FizzBuzz

Читая ужас кодирования, я просто наткнулся на FizzBuzz в другой раз.

Оригинальное сообщение здесь: Ужас кодирования: почему программисты не могут программировать?

Для тех, кто не знает: FizzBuzz - довольно популярная детская игра. Подсчитывая от 1 до 100, и каждый раз, когда число делится на 3, называя "Fizz", каждый раз число делится на 5, называя "Buzz", и каждый раз число делится на 3 и 5, вызывая "FizzBuzz вместо числа

Но на этот раз я только начал его кодировать. Это была минута, но есть несколько вещей, которые мне не нравятся.

Вот мой код

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

Итак, мои вопросы:

  • Как избавиться от найденного bool?
  • Есть ли лучший способ тестирования чем foreach?
4b9b3361

Ответ 1

Я думаю, что вы пытаетесь выполнить это универсальное решение для FizzBuzz, которое будет работать для любого количества комбинаций числовых слов.

У вас хорошее начало - думаю, я могу ответить на ваши вопросы с помощью этого примера:

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 в метод, но я включил его внутри, чтобы быть кратким.

Ответ 2

Я думаю, что ваша реализация излишне сложна. Это делает работу и ее легче понять:

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

Ответ 3

Воспользуйтесь спецификаторами условного формата, чтобы получить красивую версию для гольфа:

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

Ответ 4

Развернута для максимальной эффективности. Эта программа может outfizzbuzz всех остальных.

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

Ответ 5

Третье редактирование:

Вот один из способов "избавиться от 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);
}

Предыдущие ответы:

Для чистого решения С# проверьте решение 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);
            }
        }
    }
}

Я немного поработал над FixBuzz, используя linq. Это решения, которые я придумал - я считаю, что они представляют собой лучший способ выразить решение этой проблемы с помощью 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())
      ));
    }
}

Ответ 6

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 == 0 для квалификации FizzBuzz. Является ли это лучше для обсуждения. Однако это по-другому.

Ответ 7

Кто-нибудь уже сделал это?

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

Ответ 8

Добавит 5 центов к решению Linq. Все используют Select, который является в основном функцией Map. Функция IMHO 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());

Ответ 9

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

Ответ 10

Я думаю, вы начали со сложного пути. Улучшение этого кода было бы более сложным. Вы можете использовать временную переменную для отслеживания и отображения этой переменной в конце проверки FizzBuzz. Ниже приведен код, и вы также можете просмотреть эту деталь С# FizzBuzz 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
    }

Ответ 11

Не самый эффективный, но здесь используется С# -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())}");
    }
}

Ответ 12

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

В этом ответе есть все:

  • LINQ
  • Условное форматирование
  • Строковая интерполяция
  • Все в одной строке

Победа!

Ответ 13

Хорошо, что, черт возьми, вот решение, которое мне понравилось:)

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

Очевидно, что это не самое быстрое решение, но мне оно нравится, потому что оно подчеркивает читаемость и делает случай "FizzBuzz" больше не частным случаем, а тем, что естественно произойдет через кодовый путь.

В конце концов, что мне больше всего нравится в этом вопросе, когда мы сталкиваемся с этим, мы видим, как много разных решений ppl может придумать.

Ответ 14

Вы хотите, вероятно, настроить его, но вопрос в том, что нужно сделать настраиваемым - мы этого не знаем. Возможно, нам нужно настроить весь цикл (FizzBuzz имеет цикл). Здесь очень маленькая и веселая версия с настраиваемым циклом:

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 лучше, потому что его легче изменить.

Ответ 15

Вопрос FizzBuzz - отличный вопрос для интервью. Мы начали использовать его в нашем процессе собеседования. Поразительно, сколько людей не может решить такую ​​простую проблему.

Имейте в виду, что исходное сообщение в блоге было в конечном итоге заблокировано из-за потока людей, отправляющих больше решений. Хахаха.

Независимо, вот мой на С++! ^ _ ^

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

Ответ 16

С входом Роб Х и Якоба Кралла вот что я имею в данный момент. Возможно, я буду играть с этим в будущем... просто хотел его предоставить.

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

Ответ 17

Я бы предложил этот компактный код в качестве дополнения к предыдущим простым и приятным версиям.

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

Ответ 18

Я начинаю, вот моя попытка:

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

Что-то не так с моим подходом? Шахта кажется намного проще, чем все остальные, так что это должно быть неправильно.

Ответ 19

По моему мнению, проблема FizzBuzz всегда представляется как вызов для того, чтобы сделать слово FizzBuzz без явной печати. Вот мое решение в С#.

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

Ответ 20

Функциональный подход...

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

Ответ 21

Я попытался решить эту проблему, не глядя на ответы. Мне потребовалось 3 часа, чтобы добиться успеха. (Я просто программист по хобби, кстати, так что не bash мне тяжело, пожалуйста:)) Это мое решение для версии С#:

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

Ответ 22

Относительно простое решение с использованием цикла 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+""));

Ответ 23

Оператор нулевой коалесценции действительно полезен:

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

Ответ 24

Я добавлю свое, хотя есть еще 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++ 
}

Первое решение, с которым я столкнулся. Простой, по сути, и выполняет свою работу. Нет необходимости в bool.

Ответ 25

Я рекомендую использовать ++ я вместо я ++ в цикле for, потому что я ++ требует, чтобы была сделана копия;)

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

Ответ 26

Оригинальные вопросы: 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);
    }
} 

Кто бы хотел, чтобы мы были так взволнованы простой игрой для детей?:)

Ответ 27

Вы можете использовать либо использовать это, и только взять нужную сумму

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

Ответ 28

Очевидно, это немного вне духа задачи FizzBuzz. Но в моем тесте это было самым быстрым, что я мог сделать, пока он был однопоточным и все еще заканчивался на 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());

Ответ 29

Без условий if только один тернарный оператор.

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

Ответ 30

Без использования кода If's, С#.

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

    }