Co to jest gra FizzBuzz i jak wykorzystać ją podczas rozmowy kwalifikacyjnej

FizzBuzz

Gra FizzBuzz wykorzystywana jest na wielu rozmowach kwalifikacyjnych na programistę.
Sprawdź, czy zdasz taki test.
Wystarczy 10 minut, żeby się zapoznać z tą metodą i zwiększyć swoje szanse przy kolejnej rozmowie.

FizzBuzz to jedno z popularniejszych praktycznych zadań podczas technicznej rekrutacji na programistę. Test FizzBuzz jest zazwyczaj wykorzystywany do wstępnego odfiltrowania osób, które zwyczajnie nie potrafią programować – może wydać się to dość dziwne, ale na wstępnych rozmowach kwalifikacyjnych pojawia się zadziwiająco dużo osób, które mają problemy z rozwiązaniem nawet wyjątkowo prostych problemów programistycznych.

No dobrze, ale jaki to ma związek z dziećmi?

Dziecięca gra FizzBuzz

FizzBuzz gra dziecięca

Gra dziecięca FizzBuzz

Pierwotnie test FizzBuzz zyskał popularność jako gra przeznaczona dla dzieci, mająca na celu nauczenie ich dzielenia.

Dzieci siadały w kółeczku i kolejno musiały wymieniać liczby całkowite:

  • pierwsze dziecko – jeden;
  • drugie dziecko – dwa;
  • trzecie – trzy;
  • i tak dalej…

Cała zabawa polegała na tym, że jeżeli liczba była podzielna przez trzy, to – zamiast podania samej liczby – trzeba było krzyknąć Fizz, jeżeli była podzielna przez pięć, to Buzz, a jeżeli przez trzy i pięć, to FizzBuzz.

Świetny i wyjątkowo prosty sposób na zabawę, a jednocześnie skuteczna zachęta do nauki matematyki.

Zabawa stała się na tyle popularna, że zyskała wiele różnych odsłon, np. w formie zadań programistycznych.

Zasady gry FizzBuzz dla programistów

W podstawowej wersji dla programistów zadanie zazwyczaj przyjmuje następującą formę.

Wypisz wszystkie liczby od 1 do 100, jednak jeżeli liczba jest podzielna przez:

  • trzy – wypisz „Fizz”,
  • pięć – wypisz „Buzz”,
  • trzy i pięć wypisz „FizzBuzz”.

Niby nic trudnego – trzy „ify”, kilka linijek kodu i problem rozwiązany. Interview zaliczone.

Ale, ale…

Nie tak szybko 🙂 Wbrew pozorom nawet na podstawie tak prostego zadania można bardzo dużo dowiedzieć się o kandydacie.
Jak się za chwilę przekonasz, w zadaniu jest ukrytych kilka pułapek programistycznych i można je rozwiązać na naprawdę wiele – w tym również błędnych – sposobów.

Pierwsze rozwiązanie problemu FizzBuzz

Zacznijmy od podstawowej implementacji, która jest jednocześnie najczęściej udzielaną odpowiedzią.

Zadanie zostało rozwiązane, udało nam się udowodnić, że znamy podstawową składnię Javy.
Jeżeli to Ci wystarczy, możesz skończyć czytać ten tekst już w tym momencie.
Jeżeli jednak masz odrobinę większe ambicje i chciałbyś dowiedzieć się, w jaki sposób można wykazać się przed rekruterem czymś więcej, niż tylko podstawową składnią języka, to zapraszam do dalszej lektury.

Co jest nie tak z moim rozwiązaniem?

Powyższy kod zwraca poprawne wyniki – czyli robi to, co najważniejsze – działa. Jeżeli jednak chcesz pokazać się z jak najlepszej strony podczas rozmowy rekrutacyjnej – a zakładam, że tak właśnie jest – to rozłóżmy teraz wspólnie to zadanie na czynniki pierwsze i zastanówmy się, co możemy jeszcze poprawić.

Pamiętaj – nie ma czegoś takiego jak uniwersalnie idealne rozwiązanie.

Może co najwyżej istnieć bardzo dobre rozwiązanie w ramach naszych konkretnych założeń.

Przykładowo:

  • inaczej będzie wyglądał kod napisany z myślą o minimalnym zużyciu pamięci;
  • inaczej, jeżeli naszym głównym celem będzie czytelność rozwiązania;
  • a jeszcze inaczej, gdy naszym głównym celem jest napisanie kodu, który w przyszłości będzie możliwie łatwy do rozbudowy o nowe funkcjonalności.

Dlatego, zanim pochwalimy się, że zadanie jest skończone, warto jasno zadeklarować przy jakich założeniach powstała ta implementacja i dopytać, czy nie ma potrzeby, żebyśmy dostosowali ją do specyficznych wymagań.

Pokażesz się wtedy jako osoba, która zwraca uwagę na coś więcej niż tylko jej kilka linijek kodu i umie dostosować swoje zadanie do większej całości.

My jednak musimy coś założyć, żeby móc pójść dalej. Dlatego przyjmiemy w miarę możliwości ogólne założenie, że chcemy przygotować uniwersalne rozwiązanie oraz dodatkowo pochwalić się podstawową znajomością dobrych praktyk programistycznych, przy jednoczesnym zachowaniu czytelności kodu – czyli wszystko po trochu, bez przesadnej optymalizacji pod żadnym kątem.

Poprawiona wersja implementacji testu FizzBuzz

Jeżeli przyjrzymy się bliżej temu rozwiązaniu, to dojdziemy do wniosku, że struktura „if’ów” jest źle dobrana, przez co mamy powielone sprawdzenie tych samych warunków. Wpływa to również na pogorszenie czytelności całego rozwiązania.

Jednym ze sposobów na poprawienie implementacji jest spłaszczenie struktury warunków do jednego poziomu zagnieżdżenia. Jednak, żeby to zrobić, trzeba zauważyć, że napis FizzBuzz będzie wyświetlony tylko w przypadku, gdy liczba jest podzielna przez 15.

Poprawiona implementacja mogłaby wyglądać tak:

Sprawdzenie najpierw podzielności przez 15 poprawia czytelność i dodatkowo unikamy duplikacji kodu.
Jednak ten warunek nie wynika bezpośrednio z treści zadania i trzeba zauważyć poniższą zależność.

i%3==0 && i%5==0
=> i%15==0

Nie jest to jednak jedyny sposób na rozwiązanie tego problemu. Prześledźmy teraz najczęściej występujące błędy oraz kilka alternatywnych rozwiązań.

Na co uważać i czego unikać – główne błędy?

  • źle dobrana struktura „ifów” – omówiliśmy sobie to szczegółowo w poprzednich punktach;
  • nie pchaj wszystkiego na siłę do jednego wora – nie staraj się za wszelką cenę wykorzystać całej swojej wiedzy w tym jednym zadaniu. Przekolorowane rozwiązania, w których na siłę upychasz różne możliwości, wcale nie wyglądają dobrze. Pamiętaj o jednej z ważniejszych zasadach programistycznych: KISS (ang. keep it simple, stupid),
  • egzotyczne rozwiązania – staraj się zachować standardy i raczej unikaj nad wyraz twórczych rozwiązań. Przykładowo, resztę z dzielenia modulo w Javie można obliczyć, skorzystać z operatora modulo: x % y, ale jak ktoś się postara, to można poradzić sobie również bez niego: x-x/y*y.

Alternatywna implementacja FizzBuzz #1. – konkatenacja stringów

W tym rozwiązaniu, zamiast co chwilę wyświetlać wyniki po małym kawałku na standardowe wyjście, zbieramy wyniki i dopiero na samym końcu jedną komendą je wyświetlamy.

Standardowa konkatenacja stringów może być zastąpiona klasą StringBuilder – więcej na temat samej klasy StringBuilder oraz jej zalet w porównaniu do ręcznego łączenia stringów przeczytasz w podlinkowanym artykule.

Alternatywna implementacja FizzBuzz #2. – dodatkowa flaga boolean

Wykorzystanie pomocniczej zmiennej jest alternatywą do sprawdzania warunku na modulo 15.

Alternatywna implementacja FizzBuzz #3. – switch

W tej wersji implementacji całkowicie rezygnujemy z instrukcji warunkowej if i zastępujemy ją instrukcją switch.

Moim zdaniem takie rozwiązanie jest już trochę przekombinowane i powoli zaczynamy tracić na czytelności.

Alternatywna implementacja FizzBuzz #4. – potrójny operator warunkowy (ang. ternary operator)

Korzystając z potrójnego operatora warunkowego (ang. ternary operator), moglibyśmy nasze rozwiązanie zmieścić nawet w jednej linijce kodu.
Tylko czy warto? – tu już sami musicie sobie odpowiedzieć.

Alternatywna implementacja FizzBuzz #5. – rekurencja

Rekurencja jest potężnym orężem w ręku doświadczonego programisty. Dzięki niej można w stosunkowo prosty sposób rozwiązać nawet bardzo skomplikowane problemy. Mimo wszystko nie jest to uniwersalne rozwiązanie, które rozwiąże za nas wszystkie nasze problemy.

Pamiętaj o zasadzie złotego młotka (ang. golden hammer) i z rozwagą dobieraj rozwiązania do Twojego problemu.

Alternatywna implementacja FizzBuzz #6. – tablica

W tej wersji rozwiązania problemu FizzBuzz posłużymy się tablicą.

Alternatywna implementacja FizzBuzz #7. – wyrażenia lambda i tablica

Gdybyś chciał popisać się znajomością wyrażeń lambda, to do zadania FizzBuzz mógłbyś wykorzystać takie rozwiązanie.

Alternatywna implementacja FizzBuzz #8. – wyrażenia lambda i strumienie

Poniższe rozwiązanie wykorzystuje wyrażenia lambda oraz strumienie java (ang. java stream).

Alternatywna implementacja FizzBuzz #9. – programowanie obiektowe

Na sam koniec zostawiłem implementację w stylu OOP, gdzie wykorzystujemy programowanie obiektowe do zamodelowania rozwiązania.

Zobacz, że dzięki takiej implementacji, nie ograniczamy się na sztywno do liczb 3 i 5 oraz napisów Fizz i Buzz. Wydzielenie logiki do osobnej klasy pozwoliło przygotować bardziej uniwersalne rozwiązanie.

oraz klasa Sound.

TDD i testy jednostkowe

A co Ty na to, żeby dodatkowo przetestować swoje rozwiązanie?

Jeżeli podczas rozmowy kwalifikacyjnej dodatkowo wykażesz się znajomością dobrych praktyk i dbałością o jakość Twojego rozwiązania, może to stanowić duży plus na Twoją korzyść.
Problem FizzBuzz idealnie nadaje się do rozwiązania z wykorzystaniem testów jednostkowych i TDD (ang. test driven development).

➡ ZOBACZ 👉: Testowanie oprogramowania

Czy to już wszystko? – różne wariacje gry FizzBuzz

FizzBuzz jest na tyle popularnym problemem, że doczekał się wielu różnych modyfikacji i rozszerzeń – zaczynając od dość prostych, a kończąc na prawdziwych programistycznych wyzwaniach.
Poniżej kilka przykładowych wariacji:

  • zmiana zakresu z 1–100 do np. 100–1000 itp;
  • zmiana lub dodanie liczb, na podstawie których sprawdzamy podzielność, np. słowo Zazz dla każdej liczby podzielnej przez 10;
  • zmiana systemu liczbowego, na którym operujemy, np. z dziesiętnego na ósemkowy;
  • 3, 5, 7 Fizz Buzz Woof – gdzie jeżeli w sprawdzanej liczbie wystąpi nasza szukana, wyświetlamy odpowiadające jej słowo klucz – przykładowo liczba 3307 powinna być zamieniona na FizzFizzWoof .

Teraz Twoja kolej

Ja już rozwiązałem FizzBuzz – teraz Twoja kolej.
Zachęcam, żebyś spróbował zmierzyć się z tym zadaniem i podzielił się swoją implementacją. Szczególnie przydatne mogą okazać się inne niż Java języki programowania  – takie jak: C/C++, C#, Python, PHP itd.

Rozwiązaniem możesz podzielić się w komentarzu poniżej lub na grupie.

Teraz Ty!

Teraz Ty!

Podsumowanie FizzBuzz i co dalej?

FizzBuzz jest już swego rodzaju klasykiem technicznych rozmów kwalifikacyjnych. Dzięki temu szybkiemu ćwiczeniu w mig można sprawdzić, jak kandydat porusza się w IDE oraz jakie stosuje podejście przy programowaniu. Zadanie jest na tyle uniwersalne, że niezależnie od technologii, w której pracujesz, warto się z nim zmierzyć.

Nie twierdzę jednak, że dzięki FizzBuzz uda się potwierdzić, że ktoś jest świetnym developerem, jednak z łatwością zidentyfikujemy tych słabych. A to już coś na początek procesu rekrutacji.

Jakie Ty miałeś pytania na rozmowie kwalifikacyjnej? Podeślij mi je, to wspólnie je rozwiążemy.

Jeżeli natomiast szukasz więcej przykładowych pytań rekrutacyjnych, to dołącz do newslettera i odbierz przykładową listę z zadaniami.

4 komentarze

4 Comments

  1. FizzBuzz to chyba tylko w USA, u nas raczej się nie stosuje. Jeszcze się nie spotkałem, żeby ktoś zadał takie pytanie. Tak samo się nie spotkałem żeby ktoś zdawał pytania przy tablicy, to też w stanach raczej tak robią.

    Chyba że artykuł to tłumaczenie z angielskiego.

    1. Tomek says:

      Cześć Jakub. To wcale nie jest tak rzadko spotykane. Zdarzyło mi się już odpowiadać na pytania przy flipcharcie i rozrysowywać swoje rozwiązanie na kartce.
      Jeżeli chodzi o samo FizzBuzz, to miałem lekko zmodyfikowaną wersję – nie było to nazwane FizzBuzz, tylko trzeba było wyświetlić jakiś napis, jak liczba jest podzielna przez inną liczbę.

      Artykuł nie jest tłumaczony.

  2. Beata says:

    Pojechałeś z tymi wszystkimi sposobami 🙂 Jeśli nie ma żadnych dodatkowych wskazań, to myślę, że chyba jednak klasyczne rozwiązanie najlepsze. Wrzucam rozwiązanie w Pythonie:

    def fizz_buzz():
    for i in range(1,101):
    if i % 3 == 0 and i % 5 == 0:
    print(‘FizzBuzz’)
    elif i % 3 == 0:
    print(‘Fizz’)
    elif i % 5 == 0:
    print(‘Buzz’)
    else:
    print(i)

    1. Tomek says:

      Cześć Beata. Trochę taki był cel, żeby pokazać możliwie dużo sposobów 🙂
      Oczywiście, jak nie ma specyficznych wymagań, to nie ma co się wygłupiać.

      ps. Dzięki za rozwiązanie w Python.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Przeczytaj poprzedni wpis:
12 błędów przez które nie dostałem pierwszej pracy
12 błędów przez które nie dostałem pierwszej pracy

Mało kto lubi mówić o swoich porażkach – ja nie jestem w tej kwestii wyjątkiem. Jednak zdecydowałem się wrócić myślami...

Zamknij