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 thread on FizzBuzz in c.l.p that featured some slick maths using 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:
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
"FizzBuzz"
 
My Py3K solution:
print( ' '.join(
    'FizzBuzz' if i%15 == 0
    else 'Buzz' if i%5 == 0
    else 'Fizz' if i%3 == 0
    else str(i)
    for i 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:

Pistahh said...

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. :)

Paddy3118 said...

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.

Daniel said...

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))

Post a Comment

Subscribe Now: google

Add to Google Reader or Homepage

Go deh too!

FEEDJIT Live Traffic Map

whos.amung.us

About Me

Blog Archive