latest · next · previous · oldest

Fizzbuzz and polyrhythms

Finding a use for a useless program


Fizzbuzz is “a group word game for children” and a popular example of an interview question for programmers. As far as I can discern, discussion around Fizzbuzz in programming circles started in 2007 with a blog post by Imran Ghory.

Imran’s original point was that the vast majority of candidates for coding interviews could not code at all, so it made sense to filter them out with an extremely simple problem first, giving “FizzBuzz” as an example of one such problem. The point of the problem was that the program itself was not useful, but simple enough to weed out people who straight up cannot program.

He didn’t even bother including an example solution since the point is it was trivial.

But naturally, as this blog post and many response blog posts were discussed on forums, people would post their solutions in the comments, and this led to increasingly weird and complicated joke solutions. This was a very funny programmer joke 15 years ago, you gotta believe me.

Anyway, here’s a silly one-liner:

def fizzbuzz(count, divisors=(("fizz", "3"), ("buzz", "5"))):
    return ((lambda f: lambda i, s, idx: f(f, i, s, idx))( lambda f, i, s, idx: f( f, i, s+[divisors[idx][0]] if i % int(divisors[idx][1]) == 0 else s, idx+1) if idx < len(divisors) else "".join(s) if s else i)(i, [], 0) for i in range(1, count+1))

And if you insist on inserting linebreaks:

def fizzbuzz(count, divisors=(("fizz", "3"), ("buzz", "5"))):
    return ((lambda f: lambda i, s, idx: f(f, i, s, idx))(
        lambda f, i, s, idx:
            f(
                f,
                i,
                s+[divisors[idx][0]] if i % int(divisors[idx][1]) == 0 else s,
                idx+1
            ) if idx < len(divisors) else "".join(s) if s else i
    )(i, [], 0) for i in range(1, count+1))

At its heart it’s a single recursive lambda expression wrapped in a generator expression.

The way it works is it takes a list of “divisors” which are really tuples of labels and divisors, and as each divisor is tested, it builds a label s. If s is still empty after testing all divisors, it means none of the potential divisors divided evenly, so the generator should just yield the number itself.

Doing it this way, the values for “fizz” and “buzz” are easily overridden by simply passing different divisors.

Incidentally, if you don’t like my recursive lambda expression, there’s a much simpler one-liner that does the same thing:

def fizzbuzz(count, divisors=(("fizz", "3"), ("buzz", "5"))):
    return ("".join(divisor[0] for divisor in divisors if i % int(divisor[1]) == 0) or i for i in range(1, count+1))

Again, expanded:

def fizzbuzz(count, divisors=(("fizz", "3"), ("buzz", "5"))):
    return (
        "".join(
            divisor[0] for divisor in divisors if i % int(divisor[1]) == 0
        )
        or i
        for i in range(1, count+1)
    )

Here’s a quick and dirty command-line interface:

if __name__ == '__main__':
    from sys import argv
    for val in fizzbuzz(
        int(argv[1]) if len(argv) > 1 else 10,
        [tuple(a.split('=')) for a in argv[2:]]
        or (("fizz", "3"), ("buzz", "5"))
    ):
        print(val)
> ./fizzbuzz.py 28 bam=4 boom=7
1
2
3
bam
5
6
boom
bam
9
10
11
bam
13
boom
15
bam
17
18
19
bam
boom
22
23
bam
25
26
27
bamboom

So uh what about polyrhythms again??

After doing the above I kind of realized that maybe it has an application with musical polyrhythms.

The word “polyrhythm” is derived from “poly” meaning “many” and “rhythm” meaning “rhythm.” Rather than just a single beat, multiple beats are played concurrently.

A relatively common polyrhythm might be to play three against four, that is three beats with one hand and 4 with the other.

It’s pretty easy for most people to clap along to either 4/4 or 3/4. Clapping along with both at the same time is a bit harder.

The way that I’ve seen how people learn in practice to actually polyrhythms online is via mnemonics, eg:

B    R   L     R   L   R
Pass the bread and but-ter

This kind of “just works” because spoken English just kind of has a builtin cadence with rests that kind of just works.

I didn’t actually “go to music school” and I’m not “good at music” so maybe there’s a better way to learn them, but if you don’t know the mnemonic, I can’t think of how besides charting it out.

Fizzbuzz to the rescue!

> ./fizzbuzz.py 12 right=3 left=4
1
2
right
left
5
right
7
left
right
10
11
rightleft

…it’s simple!

Of course, right=3 means the right is playing 4/4 and left=4 means the left hand is playing 3/4, because we need to divide from the lowest common multiple. Eg., you divide 12 units of times 3 times for 3/4 and 4 times for 4/4.

Whenever there’s just a number that’s a rest; if there’s “left” or “right” just slap the table with “left” or “right”.

If you count slowly and steadily it’s not hard, and from there it’s really just a matter of practicing slowly and then slowly ramping up.

So yeah, next time you need to figure out a polyrhythm and can’t remember the mnemonic, why not code up fizzbuzz?

back to top

latest · next · previous · oldest