FizzBuzz using streams in Python

bonfacekilz

the_savage

Posted on February 13, 2020

FizzBuzz using streams in Python

So this evening I was fooling around with the concept of using monoids to play around with streams. The idea here is to break a relatively abstract concept into something that a noOb can follow along, and it hit me; why not demo all this stuff using the classic Fizz-buzz algorithm.

Generally, for a fizz-buzz problem, you print out "Fizz" if a number is divisible by 3; and alternatively, you print "Buzz" if it's divisible by 5. Needless to say, you print "FizzBuzz" if it's divisible by both 3 and 5. Now a simple implementation in python would be something like:

def fizz_buzz(n):
    for i in range(1, n+1):
        if (i % 3 == 0 and i % 5 == 0):
            print("{}: FizzBuzz".format(i))
            continue
        if (i % 3 == 0):
            print("{}: Fizz".format(i))
            continue
        if (i % 5 == 0):
            print("{}: Buzz".format(i))


fizz_buzz(100)        

Well for one, I don't like that the above function has side-effects. How can we refactor this to use streams? First of all, let's clear up what a stream is. A stream is a sequence of objects which can be accessed in sequential order. Where do monoids come in? Well a monoid allows us to combine things. A monoid has a single associative "structure"(in our case this is the "append" operation that zip provides). In this case, when we have a stream, we can combine several monoids from a stream using zip. Let's look at it in Python:

from itertools import cycle


def fizz_buzz(n):
    """Return an iter list with fizz-buzz"""
    fizz_buzz = zip(cycle(['', '', '', '', 'Fizz']),
                    cycle(['', '', 'Buzz']),
                    [i for i in range(1, n+1)])
    return filter(lambda x: (x[0] != '' or x[1] != ''),
                  fizz_buzz)

for i in fizz_buzz(100):
    print("{}: {}{}".format(i[2], i[0], i[1]))

From the above snippet, we first generate a stream of "Fizzes" and "Buzzes", then we combine them with zip after which we filter any element from the stream that has no "Fizz" or "Buzz". Python's loose typing makes it easy for us to combine and morph things. Notice that the fizz_buzz function returns a generator which has it's own merits.

If you want to functional programming tips, I post interesting reads on a google groups I started a while back here https://groups.google.com/forum/#!forum/nairobi-functional-programming-community

💖 💪 🙅 🚩
bonfacekilz
the_savage

Posted on February 13, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

FizzBuzz using streams in Python
python FizzBuzz using streams in Python

February 13, 2020