Hacker News new | ask | show | jobs
by jimmahoney 3526 days ago
Here's a different sort-of-functional python fizzbuzz.

While it doesn't use the spiffy lazy lists of itertools, and does have the typical "if x % n == 0" test, it does generalize easily to the "and print Baz every 37th number" case.

  def joinmap(func, elements, separator):
    return separator.join(map(func, elements))

  def fb_value(x, fb={3:'Fizz', 5:'Buzz'}):
    words = joinmap(lambda n: fb[n] if x % n == 0 else '', fb.keys(), '')
    return words if words else str(x)

  def fb_range(low=1, high=100):
    return joinmap(fb_value, range(low, 1 + high), '\n')

  print fb_range()
1 comments

That's excellent!

Treating a dictionary as an iterator automatically iterates over its .keys(), so you can remove the .keys() in fb.keys() and just map over fb itself.

>>> map(lambda x: x+x, {2: "who", 4: "do", 6: "we", 8: "appreciate"})

[16, 4, 8, 12]

A problem that this highlights is that the order in which the Fizz and Buzz and other strings get concatenated depends on the order of the underlying dictionary hash, which can be thought of as random. In Python 3 it even changes from run to run.

https://docs.python.org/3/whatsnew/3.3.html#summary-release-...

$ python3 -c 'print(list({"foo": "bar", "baz": "qux"}))'

['foo', 'baz']

$ python3 -c 'print(list({"foo": "bar", "baz": "qux"}))'

['baz', 'foo']

For predictable behavior across larger sets of divisors, and for consistent behavior on Python 3, you'd probably want to use collections.OrderedDict.