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ślinjest podzielne przez 3 i przez 5"Fizz"jeślinjest podzielne przez 3"Buzz"jeślinjest 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
% 15przed% 3i% 5(lub buduje string kumulatywnie) - Czytelność —
% 15vs% 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 —
-15też 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.
🚀 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.
- 🗺️ Pobierz darmową roadmapę Junior .NET Developer — 12 kroków od podstaw C# do pierwszej pracy: dev-hobby.pl
- 🎬 Subskrybuj kanał YouTube — nowe filmy co tydzień.
13 comments
Dodaj komentarz
Musisz się zalogować, aby móc dodać komentarz.
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ę →
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);
}
}
Dzięki za Twoje rozwiązanie, działa 🙂 , pozdrawiam
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);
}
Dzięki za Twoje rozwiązanie, również działa 🙂 , pozdrawiam
for (int i = 1; i <= 100; i++)
{
string res = (i % 3 == 0 && i % 5 == 0) ? "FizzBuzz" :
(i % 3 == 0) ? "Fizz" :
(i % 5 == 0) ? "Buzz" :
i.ToString();
Console.WriteLine(res);
}
Dzięki za Twoje rozwiązanie, również oczywiście działa 🙂 , pozdrawiam
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);
}
}
Dzięki za Twoje rozwiązanie, również działa 🙂 , pozdrawiam
Paul Getty Zwykle Twierdzil, że bezinteresowna przyjazń może istnieć tylko pomiedzy osobami o jednakowych dochodach. I ja sie po niekąd z tym zgadzam 🙂 A ty ?