I passed a fizzbuzz test but failed at recursion.

B

Bill

Look at this recursive fizzbuzz function from
http://www.codinghorror.com/blog/2007/02/why-cant-programmers-program.html

def fizzbuzz(num):
if num:
if num % 15 is 0: return fizzbuzz(num-1) + 'fizzbuzz \n'
elif num % 5 is 0: return fizzbuzz(num-1) + 'buzz \n'
elif num % 3 is 0: return fizzbuzz(num-1) + 'fizz \n'
else : return fizzbuzz(num-1) + ('%d \n' % num)
return ''
print fizzbuzz(100)

This returns "1 2 fizz 4 ...etc... 97 98 fizz buzz" which is correct.

However, when I try to decipher the logic of the function I imagine
the solution reversed as "buzz fizz 98 97 ...etc... 4 fizz 2 1".

After all, the first num is 100 which decrements by one until a zero
stops the recursive loop.

My (faulty) reasoning is that fizzbuzz(100) would firstly print a
"fizz" and the last fizzbuzz(1) would finally print a "1".

My logic is wrong, but I don't know why.
 
C

Chris Hulan

Look at this recursive fizzbuzz function fromhttp://www.codinghorror.com/blog/2007/02/why-cant-programmers-program...

def fizzbuzz(num):
    if num:
        if num % 15 is 0: return fizzbuzz(num-1) + 'fizzbuzz \n'
        elif num % 5 is 0: return fizzbuzz(num-1) + 'buzz \n'
        elif num % 3 is 0: return fizzbuzz(num-1) + 'fizz \n'
        else : return fizzbuzz(num-1) + ('%d \n' % num)
    return ''
print fizzbuzz(100)

This returns "1 2 fizz 4 ...etc... 97 98 fizz buzz" which is correct.

However, when I try to decipher the logic of the function I imagine
the solution reversed as "buzz fizz 98 97 ...etc... 4 fizz 2 1".

After all, the first num is 100 which decrements by one until a zero
stops the recursive loop.

My (faulty) reasoning is that fizzbuzz(100) would firstly print a
"fizz" and  the last fizzbuzz(1) would finally print a "1".

My logic is wrong, but I don't know why.

There's only one print, it prints the string returned by fizzbuzz(100)
The string is constructed via recursion
ie:
fizzbuzz(6)
fizzbuzz(5)
fizzbuzz(4)
fizzbuzz(3)
fizzbuzz(2)
fizzbuzz(1)
fizzbuzz(0)
''+'1 \n'
'1 \n'+'2 \n'
'1 \n2 \n'+'fizz \n'
'1 \n2 \n fizz \n'+'4 \n'
'1 \n2 \n fizz \n4 \n'+'buzz \n'
'1 \n2 \n fizz \n4 \nbuzz \n'+'fizz \n'

print '1 \n2 \n fizz \n4 \nbuzz \nfizz \n'

clear as mud ;)
 
T

Terry Reedy

Look at this recursive fizzbuzz function from
http://www.codinghorror.com/blog/2007/02/why-cant-programmers-program.html

def fizzbuzz(num):
if num:
if num % 15 is 0: return fizzbuzz(num-1) + 'fizzbuzz \n'
elif num % 5 is 0: return fizzbuzz(num-1) + 'buzz \n'
elif num % 3 is 0: return fizzbuzz(num-1) + 'fizz \n'

In all 3 branches, 'is' should be '=='. As written, this code depends on
the implementation treating 0 as a singleton, which CPython does as an
optimization, but which the language def does not require.
else : return fizzbuzz(num-1) + ('%d \n' % num)
return ''
print fizzbuzz(100)

This returns "1 2 fizz 4 ...etc... 97 98 fizz buzz" which is correct.

However, when I try to decipher the logic of the function I imagine
the solution reversed as "buzz fizz 98 97 ...etc... 4 fizz 2 1".

After all, the first num is 100 which decrements by one until a zero
stops the recursive loop.

My (faulty) reasoning is that fizzbuzz(100) would firstly print a
"fizz" and the last fizzbuzz(1) would finally print a "1".

If one reversed the string addition in each branch, it would.
As written, the 'word' for n is tacked on at the end.
My logic is wrong, but I don't know why.

Is this slightly revised version any clearer?

def fizzbuzz_rb(n):
if n:
previous = fizzbuzz_rb(n-1)
word = (not n % 15 and 'fizzbuzz \n' or
not n % 5 and 'buzz \n' or
not n % 3 and 'fizz \n' or
'%d \n' % n)
return previous + word
else:
return ''

or this equivalent tail-recursive version?

def fizzbuzz_rt(i,n,s):
if i <= n:
word = (not i % 15 and 'fizzbuzz \n' or
not i % 5 and 'buzz \n' or
not i % 3 and 'fizz \n' or
'%d \n' % i)
return fizzbuzz_rt(i+1, n, s+word)
else:
return s

or this equivalent iterative version?

def fizzbuzz_it(n):
s = ''
for i in range(1,n+1):
s += (not i % 15 and 'fizzbuzz \n' or
not i % 5 and 'buzz \n' or
not i % 3 and 'fizz \n' or
'%d \n' % i)
return s

print (fizzbuzz_rb(100) == fizzbuzz_rt(1,100,'') == fizzbuzz_it(100))
# prints True

Terry Jan Reedy
 
M

Michael Rudolf

Am 10.03.2010 16:55, schrieb Bill:
def fizzbuzz(num):
if num:
if num % 15 is 0: return fizzbuzz(num-1) + 'fizzbuzz \n'
elif num % 5 is 0: return fizzbuzz(num-1) + 'buzz \n'
elif num % 3 is 0: return fizzbuzz(num-1) + 'fizz \n'
else : return fizzbuzz(num-1) + ('%d \n' % num)
return ''
print fizzbuzz(100)

While I do understand that this is not a Perl group, and this probably
won't help the OP, I just could not resist:

for i in range(1,101):print('','fizz')[not i%3]+('','buzz')[not i%5]or i
> However, when I try to decipher the logic of the function I imagine
> the solution reversed as "buzz fizz 98 97 ...etc... 4 fizz 2 1".

No, the function creates the string from right to left.
See:
fizzbuzz(100) = fizzbuzz(99) + "buzz \n"
= fizzbuzz(98) + "fizz \n" + "buzz \n"

....

= fizzbuzz(1) + "2 \n" + "fizz \n" + "4 \n" + "buzz\n " + "fizz \n" +
..... + "97 \n" + "98 \n" + "fizz \n" + "buzz \n"

= fizzbuzz(0) + "1 \n" + "2 \n" + "fizz \n" + "4 \n" + "buzz\n " + "fizz
\n" + .... + "97 \n" + "98 \n" + "fizz \n" + "buzz \n"

= " " + "1 \n" + "2 \n" + "fizz \n" + "4 \n" + "buzz\n " + "fizz \n" +
..... + "97 \n" + "98 \n" + "fizz \n" + "buzz \n"

Regards,
Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top