Mainly Tech projects on Python and Electronic Design Automation.

Saturday, June 21, 2008

More Fizz than Buzz

I
downloaded the first beta release of Python 3 which corresponded with
another href="http://groups.google.com/group/comp.lang.python/msg/e7acbdd108a0ea05">thread
on FizzBuzz in c.l.p that featured some slick maths using href="http://en.wikipedia.org/wiki/Fermats_little_theorem">Fermats
little theorem, (yep it's really called that). I learnt a
little about the theorem, did a quick spreadsheet to show that it
worked, but could not grasp how they made it work in their examples.

It
did however get me toying with Py3K where I came up with this snippet
of code from the description of the problem.

The
Problem:
face="Courier, Monospaced">Write a program that prints the
numbers from 1 to 100. But for
multiples of three print
"Fizz" instead of the number and for the
multiples of five
print "Buzz". For numbers which are multiples of
both three
and five print class="fixed_width"> " style="font-family: monospace;">FizzBuzz"
 
My
Py3K solution:
style="margin-left: 40px; font-family: monospace;">
print( ' color="#ff00ff"> '.join(
    ' color="#ff00ff">FizzBuzz' color="#804040">if i%15 == 0
     color="#804040">else ' color="#ff00ff">Buzz' if i%5 == 0
     color="#804040">else ' color="#ff00ff">Fizz' if i%3 == 0
     color="#804040">else str(i)
     color="#804040">for i color="#804040">in range(1,101)))

What
I like about this
solution is it applies the constraints from the problem description in
the (reverse) order that they are given, and does not rely on the
elementary (to pythoneers), knowledge that a test for not(X) is
equivalent to a test of whether X==0. I'd be happy to put this in, say
a Wikipedia type article on FizzBuzz, or teach it to newbies ready for
immersion into gencomps (as maybe the second or third
example). 

- One for trainers.

-
Paddy.

3 comments:

  1. What I do not like in your solution is that it uses the % operator more than it should.

    If you know a number is divisible by 3 and it is divisible by 5, you can be sure that it is also divisible by 15, so it is enough to test for 3 and 5 only.

    So for every 14 number out of 15 your (% 15) test is unnecessary. :)

    ReplyDelete
  2. True, but do you know a way of doing the test using just two modulo ops in a comprehension?
    If I try I get:

    ' '.join(
    'FizzBuzz' if j[:2] == [0,0]
    else 'Buzz' if j[1] == 0
    else 'Fizz' if j[0] == 0
    else str(j[2])
    for j in ([i%3, i%5, i] for i in range(1,101)))

    And it is less clear in that you have to explain the intermediate list produced for the if to work on. In the original, you only have to explain modulo 15 which should be obvious.

    - Paddy.

    ReplyDelete
  3. I know it requires a pre-func, and you could just put the data list inside the statement (it just would decrease readability alot) but how about?

    def default(value, defval, otherval):
    if value == defval:
    return otherval
    else:
    return value

    data = [(3,'Fizz'),
    (5, 'Buzz')]

    print ' '.join(default(''.join((s for n,s in data if i%n==0)), '', str(i)) for
    i in range(1, 101))

    ReplyDelete

Followers

Subscribe Now: google

Add to Google Reader or Homepage

Go deh too!

whos.amung.us

Blog Archive