FizzBuzz

cs v kategorii code • 11 min. čtení
Mind the age! Most likely, its content is outdated. Especially if it’s technical.

FizzBuzz zná zřejmě každý programátor. Není to nic těžkého, implementace může vypadat třeba takto:

for index in range(1, 20):
    if index % 15 == 0:
        print 'FizzBuzz'
    elif index % 3 == 0:
        print 'Fizz'
    elif index % 5 == 0:
        print 'Buzz'
    else:
        print index

Ale to není sranda. Sice je to úloha na rychlé vyřazení špatných programátorů, ale paradoxně selhávají i schopní, protože se snaží na první dobrou napsat řešení nějak chytře (rozuměj one-linově). A nepovede se. Třeba:

for index in range(1, 20):
    print 'Fizz' * int(index % 3 == 0) + 'Buzz' * int(index % 5 == 0) or index

Ale to stále není sranda. Třeba takový Javista by mohl namítnout, že v tom je málo tříd…

class FizzBuzzNumber(int):
    def __str__(self):
        return (self.fizz + self.buzz) or super(FizzBuzzNumber, self).__str__()

    @property
    def fizz(self):
        return 'Fizz' if self.is_fizz else ''

    @property
    def buzz(self):
        return 'Buzz' if self.is_buzz else ''

    @property
    def is_fizz(self):
        return self % 3 == 0

    @property
    def is_buzz(self):
        return self % 5 == 0

for index in range(1, 20):
    print FizzBuzzNumber(index)

Mně to přišlo ale stále málo crazy. Když už mám třídu, proč si nevytvořit dynamicky třídu pro každé číslo. Když to jde, že?

class FizzBuzzNumberType(type):
    _class_cache = {}

    def __new__(mcs, name, bases, attributes):
        return mcs.create_instance

    @classmethod
    def create_instance(cls, number):
        return cls.create_or_get_class(number)(number)

    @classmethod
    def create_or_get_class(cls, number):
        if number not in cls._class_cache:
            cls._class_cache[number] = cls.create_class(number)
        return cls._class_cache[number]

    @classmethod
    def create_class(cls, number):
        printable_number = cls.get_printable_number(number)
        attributes = {
            '__str__': lambda self: printable_number,
        }
        new_cls = type.__new__(FizzBuzzNumberType, 'FizzBuzzNumber({})'.format(number), (int,), attributes)
        return new_cls

    @staticmethod
    def get_printable_number(number):
        return 'Fizz' * int(number % 3 == 0) + 'Buzz' * int(number % 5 == 0) or str(number)


class FizzBuzzNumber(int):
    __metaclass__ = FizzBuzzNumberType


for index in range(1, 20):
    print FizzBuzzNumber(index)

Tím sranda nemusí končit. Můžeme klidně pokračovat generováním kódu z XML. Aneb můžeme programovat aniž bychom museli měnit kód!

Ale to už je fakt za hranicí šílenosti. Pojďme zkusit něco jiného. Co třeba CSS?

.fizzbuzz {
    counter-increment: index;
}
.fizzbuzz:nth-of-type(n)::before{
    content: counter(index);
}
.fizzbuzz:nth-of-type(5n)::before{
    content: "";
}
.fizzbuzz:nth-of-type(3n)::before{
    content: "fizz";
}
.fizzbuzz:nth-of-type(5n)::after{
    content: "buzz";
}

Kam se hrabe JavaScript. :-)

Přemýšlel jsem, v čem ještě by šlo implementovat FizzBuzz. Vzpomněl jsem si na hlášku: Když se někteří lidé setkají s problémem, pomyslí si: „Já vím! Použiji regulární výrazy.“ V tom okamžiku mají problémy dva.

seq 1 19 | sed -r '3~3 s/[0-9]*/Fizz/; 5~5 s/[0-9]*$/Buzz/'

A taky že ano. První řešení je velice jednoduché. Tak ještě jednou bez počítání řádků!

seq 1 19 | sed -r 's/^([0369]|[258][0369]*[147]|[147]([0369]|[147][0369]*[258])*[258]|[258][0369]*[258]([0369]|[147][0369]*[258])*[258]|[147]([0369]|[147][0369]*[258])*[147][0369]*[147]|[258][0369]*[258]([0369]|[147][0369]*[258])*[147][0369]*[147])*$/Fizz\1/;s/^Fizz[0-9]*[05]$/FizzBuzz/; s/^Fizz[0-9]*$/Fizz/; s/^[0-9]*[05]$/Buzz/'

Ufff. Šlo by to napsat s menším počtem kroků, ale jeden konečný automat mi pro dnešek stačil.

Co vy, máte taky nějaký crazy FizzBuzz?

P.S.: Pro silnější nátury jsem narazil na oblíbený Brainfuck. A pro ověření si můžete udělat vlastní interpreter. :-)






3 reakce

Jediná správná varianta je FizzBuzz Enterprise Edition https://github.com/EnterpriseQualityCoding/Fizz... . Doporučuji projít i issues - samá perla :-)

Když jsem objevil FizzBuzz Enterprise Solution, tak jsem šel do kolen:

https://github.com/EnterpriseQualityCoding/Fizz...

Ok. Má FizzBuzz řešení jsou oproti FizzBuzzEnterpriseEdition komická. :-)





Může se vám také líbit

en Makefile with Python, November 6, 2017
en Fast JSON Schema for Python, October 1, 2018
en Deployment of Python Apps, August 15, 2018
cs Jasně, umím Git…, August 6, 2014
cs Checklist na zabezpečení webových aplikací, March 1, 2016

Další články z kategorie code.
Nenechte si ujít nové články díky Atom/RSS kanálu.



Poslední příspěvky

cs Mami, tati, přejde to, December 9, 2023 in family
cs Co vše bychom měli dělat s dětmi?, November 24, 2023 in family
cs O trávicí trubici, November 7, 2023 in family
cs Na šestinedělí se nevyspíš, October 28, 2023 in family
cs Copak to bude?, October 20, 2023 in family