Click here to Skip to main content
Click here to Skip to main content
Go to top

FizzBuzz

, 31 Oct 2012
Rate this:
Please Sign up or sign in to vote.
FizzBuzz is variously a drinking game, a math game, a way of learning numbers in a foreign language and more importantly (for this blog) a programming kata.

FizzBuzz is variously a drinking game, a math game, a way of learning numbers in a foreign language and more importantly (for this blog) a programming kata. The principle of FizzBuzz is a counting and substitution game you count to a limit and replace some numbers with words. In the classic example you replace any number which is divisible by 3 with Fizz and any number divisible by 5 with Buzz, and any number which is divisible by both with FizzBuzz.

So a classic game to 20 looks like this:

    1
    2
    Fizz
    4
    Buzz
    Fizz
    7
    8
    Fizz
    Buzz
    11
    Fizz
    13
    14
    FizzBuzz
    16
    17
    Fizz
    19
    Buzz

It is fairly trivial to make a program to print lists like this out and can be done with some basic programming skill. This is a Python function which, given a limit, will print numbers under the limit with the required replacements.

#==============================================================================
def fizz_buzz(limit):
    """ 
    For the each number in 1 - limit inclusivly, this function prints either;
    the number, Fizz if it is divisible by 3, Buzz if it is divisible by 5 and
    FizzBuzz if it's divisible by both.
    """
    for i in range(1, limit + 1):
        if (i % 15 == 0):
            print("FizzBuzz")
        elif (i % 5 == 0):
            print("Buzz")
        elif (i % 3 == 0):
            print("Fizz")
        else:
            print(i)

This is a nice and simple function that can be followed fairly easily. It loops over the values 1 – limit inclusively, if the number is divisible by 3 and 5 it prints FizzBuzz, if the number is divisible by 5 it prints Buzz, if it is divisible by 3 it prints Fizz, and if none of the above it prints the number.

This is all well and good, but it’s when you are asked to expand the rules that this approach falls down. For instance this only has one special case but if you want to say Pop rather than a multiple of 7 then the function becomes this.

#==============================================================================
def fizz_buzz_pop(limit):
    """ 
    For the each number in 1 - limit inclusivly, this function prints either;
    the number, Fizz if it is divisible by 3, Buzz if it is divisible by 5, Pop
    if it's divisible by 7, FizzBuzz if it's divisible by both 3 and 5, FizzPop
    if it's divisible by both 3 and 7, BuzzPop if it's divisible by 5 and 7 and
    FizzBuzzPop if it's divisible by 3, 5 and 7.
    """
    for i in range(1, limit + 1):
        if (i % 105 == 0):
            print("FizzBuzzPop")
        elif (i % 35 == 0):
            print("BuzzPop")
        elif (i % 21 == 0):
            print("FizzPop")
        elif (i % 15 == 0):
            print("FizzBuzz")
        elif (i % 7 == 0):
            print("Pop")
        elif (i % 5 == 0):
            print("Buzz")
        elif (i % 3 == 0):
            print("Fizz")
        else:
            print(i)

And of course if you say that multiples of 11 become Bizz you get into real trouble.

I feel a more generic approach is needed here. Here is a fairly simple class called AdvancedFizzBuzz which will give us a fully extensible FizzBuzz machine.

#==============================================================================
class AdvancedFizzBuzz(object):

    def __init__(self, mapping):
        """ 
        mapping should be a dictionary with numbers as keys and what to print 
        as what it is mapped to. 
        
        e.g FizzBuzz is using a dictionary with:
          mapping[3] = Fizz
          mapping[5] = Buzz
        """
        self.map = mapping

    def __getitem__(self, index):
        ret_val = ""
        modified = False
        for key in self.map:
            if (index % key == 0):
                modified = True
                ret_val += self.map[key]
        if (not modified):
            ret_val = index
        return ret_val

    def run(self, limit):
        for i in range(1, limit + 1):
            print(self[i])

The constructor takes a dictionary which maps numbers to what to print instead of their multiples. This is fairly straight forward and as it says in the doc string if you give it a dictionary with mapping[3] = Fizz, mapping[5] = Buzz it will be FizzBuzz.

The function __getitem__() is more mysterious if you are not familiar with pythons magic methods. If you aren’t then I hugely recommend this guide, it has helped me enormously. What this function does is make your class indexable, just like a list or dictionary.

What the function actually does is the work of this class. It looks through all it’s rules (they keys in it’s map) and finds if the number it has been given is divisible by them. If it is divisible then it will append it’s key word onto the string to be returned and also mark the the value as modified. If the value has been modified it returns the string otherwise it returns the number itself.

The run() function is self-explanatory it goes through 1 – limit inclusively and prints the return value from the previous function.

This means that this class does not need editing to extend it’s functionality. I simply provide a different dictionary of rules. The results of running the function fizz_buzz_pop(110) and using the class with the dictionary {3: ‘Fizz’, 5: ‘Buzz’, 7: ‘Pop’} are given as text files in this repository. I used 110 so that it got to at least the first FizzBuzzPop which is at 105.

And of course this means that rather than writing a new function for multiples of 11 being Bizz you use the dictionary {3: ‘Fizz’, 5: ‘Buzz’, 7: ‘Pop’, 11: ‘Bizz’}.

The source code used in this article can be found in this repository.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

David Corne
Software Developer
United Kingdom United Kingdom
I am a C++ developer with a strong interest in Python, C#, and Qt. I work on a native C++ application which uses COM to call C# in order to use a WPF GUI.
 
While I develop an application using WPF exclusivly for windows, I am a big linux user. My favourite distro at the moment is Linux Mint, and I love the delights of the command line,.
 
If you've read something of mine and you enjoyed it, check out my blog.
 
I am also active on various other sites, listed below.

Coding Sites

  • BitBucket where I keep the majority of my projects.
  • GitHub where I have a few older projects. This includes my current long term project, I'm writing a book about design patterns in python. Find the repository here and blog posts about individual patterns here
  • Stackoverflow I'm not too active on stackoverflow, I'm more of a listener.
  • coderwall and coderbits two profile compilation websites.

Social Sites

Follow on   Twitter   Google+

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140905.1 | Last Updated 31 Oct 2012
Article Copyright 2012 by David Corne
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid