🔥 Zapisy zamknięte, ale możesz pobrać Roadmapę .NET i dołączyć do listy oczekujących — Pobierz i dołącz do Listy VIP →

FizzBuzz w C# — zadanie rekrutacyjne z pułapką

Czego szuka rekruter: rozumienie operatora modulo, warunki złożone, kolejność sprawdzania warunków
Poziom: Junior


Zadanie

Napisz funkcję, która dla liczby całkowitej n zwraca:

  • "FizzBuzz" jeśli n jest podzielne przez 3 i przez 5
  • "Fizz" jeśli n jest podzielne przez 3
  • "Buzz" jeśli n jest podzielne przez 5
  • string z liczbą w pozostałych przypadkach

Wyświetl wyniki dla liczb 1–100.


Czego szuka rekruter

FizzBuzz nie jest testem wiedzy o operatorze modulo — to test myślenia. Rekruter patrzy na:

  • Kolejność warunków — czy kandydat sprawdza % 15 przed % 3 i % 5 (lub buduje string kumulatywnie)
  • Czytelność% 15 vs % 3 == 0 && % 5 == 0
  • Ekstrakcja do metody — czy kandydat wydziela logikę z pętli
  • Rozszerzalność — co gdyby dodać “Jazz” dla 7?

Najczęstszy błąd: sprawdzanie % 3 i % 5 osobno i pisanie "Fizz" + "Buzz" bez sprawdzenia % 15 — co i tak daje "FizzBuzz", ale drugi if nadpisuje wynik jeśli kandydat użył else if.


Edge cases do przemyślenia

  • n = 0 — podzielne przez wszystko (0 % n == 0 dla każdego n > 0)
  • liczby ujemne — -15 też jest podzielne przez 15
  • n = 1 — żadna z reguł

Rozwiązanie

static string FizzBuzz(int n)
{
    // Budowanie stringa kumulatywnie — rozszerzalne
    var result = string.Empty;
    
    if (n % 3 == 0) result += "Fizz";
    if (n % 5 == 0) result += "Buzz";
    
    return result.Length > 0 ? result : n.ToString();
}

// Użycie:
for (int i = 1; i <= 100; i++)
    Console.WriteLine(FizzBuzz(i));

Alternatywa — ternary (czytelna, ale mniej rozszerzalna)

static string FizzBuzz(int n) =>
    n % 15 == 0 ? "FizzBuzz" :
    n % 3  == 0 ? "Fizz" :
    n % 5  == 0 ? "Buzz" :
    n.ToString();

Alternatywa — switch expression z tuple pattern (C# 8+)

Nowoczesny, deklaratywny zapis tej samej logiki — czytelny jak tabela decyzyjna:

static string FizzBuzz(int n) => (n % 3, n % 5) switch
{
    (0, 0) => "FizzBuzz",
    (0, _) => "Fizz",
    (_, 0) => "Buzz",
    _      => n.ToString()
};

Krotka (n % 3, n % 5) jest dopasowywana do wzorców — _ oznacza “dowolna wartość, nieistotna”. To rozwiązuje ten sam problem kolejności co wersja kumulatywna (przypadek (0, 0) jest sprawdzany jako pierwszy), ale w formie, która czyta się jak specyfikacja zadania.

Alternatywa — LINQ (na rozmowie rekrutacyjnej można pokazać jako bonus)

var output = Enumerable.Range(1, 100).Select(FizzBuzz);
foreach (var line in output)
    Console.WriteLine(line);

Rozszerzalność w praktyce — dokładanie reguły “Jazz”

Wersja kumulatywna pokazuje swoją przewagę, gdy trzeba dołożyć kolejną regułę — np. “Jazz” dla liczb podzielnych przez 7 — bez przepisywania istniejącej logiki:

static string FizzBuzz(int n)
{
    var result = string.Empty;

    if (n % 3 == 0) result += "Fizz";
    if (n % 5 == 0) result += "Buzz";
    if (n % 7 == 0) result += "Jazz";   // nowa reguła — jedna linijka, zero zmian gdzie indziej

    return result.Length > 0 ? result : n.ToString();
}

// FizzBuzz(105) => "FizzBuzzJazz" (105 = 3 × 5 × 7)

Ta sama zmiana w wersji ternary albo switch expression wymagałaby dopisania nowej gałęzi i przemyślenia wszystkich kombinacji z istniejącymi warunkami — przy trzech regułach to jeszcze do ogarnięcia, ale przy czterech czy pięciu liczba kombinacji rośnie szybko. To konkretny argument, dlaczego “rozszerzalność” bywa ważniejsza od zwięzłości.


Testy jednostkowe

[Theory]
[InlineData(1,   "1")]
[InlineData(3,   "Fizz")]
[InlineData(5,   "Buzz")]
[InlineData(15,  "FizzBuzz")]
[InlineData(30,  "FizzBuzz")]
[InlineData(100, "Buzz")]
[InlineData(99,  "Fizz")]
public void FizzBuzz_ReturnsCorrectValue(int input, string expected)
{
    Assert.Equal(expected, FizzBuzz(input));
}

Co powiedzieć na rozmowie

“Wersja kumulatywna z dwoma osobnymi if jest lepsza niż if/else if z % 15, bo łatwiej ją rozszerzyć — gdyby trzeba było dodać ‘Jazz’ dla 7, wystarczy dołożyć jeden if (n % 7 == 0) result += "Jazz" bez przepisywania całej logiki. Switch expression z tuple pattern to z kolei najczytelniejsza wersja, gdy zestaw reguł jest ustalony i się nie zmienia.”


FAQ

Dlaczego FizzBuzz w ogóle pada na rozmowach, skoro to “trywialne” zadanie?
Właśnie dlatego, że jest proste — pozwala rekruterowi w 5 minut zobaczyć, jak kandydat myśli o czytelności, kolejności warunków i rozszerzalności, zamiast tracić czas na zrozumienie skomplikowanego problemu.

Czy wydajność ma tu znaczenie?
Dla 100 iteracji — nie, żadne z powyższych podejść nie zrobi różnicy. Gdyby zakres był ogromny (miliony liczb) i budowanie wyniku odbywało się w pętli sklejającej cały raport w jeden string, dopiero wtedy warto pomyśleć o StringBuilder — patrz artykuł o efektywnym manipulowaniu stringiem.


Powiązane: to zadanie ćwiczy operator modulo i kolejność warunków — teorię znajdziesz w operatorach w C# i instrukcjach warunkowych.

👨‍💻
Mariusz Jurczenko
Senior .NET Developer · 10+ lat doświadczenia komercyjnego

Programista .NET z doświadczeniem komercyjnym w firmach takich jak NFZ, Kamsoft, Diagnostyka, Hermes Reply Polska czy Etisoft Smart Solutions. Twórca kursów, z których skorzystało już ponad 11 000 osób w Strefie Kursów i ponad 1 000 kursantów na dev-hobby.pl.

Specjalizacja: Clean Code, Clean Architecture i uczenie programowania tak, żeby dało się je naprawdę zrozumieć — nie wykuć.

🚀 Co dalej?

Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.

13 comments

  1. Oto moje rozwiązanie
    for (int i = 1; i <= 100; i++)
    {
    if (i % 3 == 0 && i % 5 == 0)
    {
    Console.WriteLine("FizzBuzz");
    }
    else if (i % 3 == 0)
    {
    Console.WriteLine("Fizz");
    }
    else if (i % 5 == 0)
    {
    Console.WriteLine("Buzz");
    }
    else
    {
    Console.WriteLine(i);
    }
    }

  2. Bardzo częste zadanie rekrutacyjne, moje rozwiązanie
    for (int i = 1; i <= 100; 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);
    }

  3. ja tez mam rozwiazanie
    private static 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);
    }
    }

Dodaj komentarz

czytanie to początek

Zamień wiedzę w umiejętności

Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.

Pobieram roadmapę →