5
\$\begingroup\$

Is this a good solution for FizzBuzz? What can I do better?

for num in range(1, 101):
    if num % 3 == 0:
        if num % 5 == 0:
            print("FizzBuzz")
        else:
            print("Fizz")
    elif num % 5 == 0:
        print("Buzz")
    else:
        print(num)
\$\endgroup\$
0
4
\$\begingroup\$

It's a good attempt, it reads easily and I like that you nested the FizzBuzz check within Fizz branch.

This doesn't look like most of the code you see in the wild, though, so a good exercise would be to extract a function for the FizzBuzz logic that is independent from the loop over numbers.

def get_fizzbuzz(num:int) -> str:
    result = ""
    # fizzbuzz logic
    if num % 3 == 0:
        if num % 5 == 0:
            result = "FizzBuzz"
        # ...
    return result

You could even make it more flexible by optionally allowing different numbers to be entered instead of 3 and 5, while still using 3 and 5 as default values, like so:

 def get_fizzbuzz(num:int, fizz:int = 3, buzz:int = 5) -> str:
    result = ""
    # fizzbuzz logic
    if num % fizz == 0:
        if num % buzz == 0:
            result = "FizzBuzz"
        # ...
    return result   

Then you can just call the function in a loop using the default values:

for num in range(1, 101):
    print(get_fizzbuzz(num))

Or alternatively with different values for fizz and buzz:

for num in range(1, 101):
    print(get_fizzbuzz(num, 5, 7))

That will help you make your code more modular.

Note that I used Python 3's type hints in the function definition, which are completely optional but can make the code more clear, as well as provide static code analysis with certain tools.

\$\endgroup\$
2
\$\begingroup\$

The True and False of Python evaluates to 1 and 0 respectively. In Python, if you multiply a str with a number, you'll get that many str, so 2*'fizz' would be, "fizzfizz". 0*"fizz" would yield ''.


With that in mind, this

if num % 3 == 0:
    if num % 5 == 0:
        print("FizzBuzz")
    else:
        print("Fizz")
elif num % 5 == 0:
    print("Buzz")

could be re written as:

print("fizz"*(num % 3 == 0)+"buzz"*(num % 5 == 0))

but now we need to do something with the printing of the ints.


Python provides an operator here: or. It is mainly used in if statements, but can also be used in-line:

variable = False or 2
>>> variable = 2

and:

variable = True or 2
>>> variable = True

so the printing of the ints is done by slapping or num on the expression:

print("fizz"*(num % 3 == 0)+"buzz"*(num % 5 == 0) or num)

since '' evaluates to False in Python.


So your code could be rewritten as

for num in range(1, 101):
    print("fizz"*(num % 3 == 0)+"buzz"*(num % 5 == 0) or num)

with exactly the same logic as in your original code.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is a nice/smart solution but it's just too hard to understand for such an easy task. \$\endgroup\$ – Grajdeanu Alex Feb 7 at 10:35
  • \$\begingroup\$ A perfect example of how a clever solution is not the same thing as a good solution. \$\endgroup\$ – Turksarama Feb 8 at 5:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.