Search code examples
pythonmathprimesfizzbuzz

Can FizzBuzz be done using arithmetic only?


I'm trying to find a way to do the FizzBuzz problem (print all numbers between 1 and 100, print Fizz if it's a multiple of 3, print Buzz if it's a multiple of 5 and FizzBuzz if it's both) using arithmetic only.

It's fairly easy if you do it using the traditional 3 and 5 because you can use this method to return 0 if it is a multiple of 3:

(i*i)%3

and this can be implemented to print the first part of "FizzBuzz"

print("FizzBuzz"[((i*i)%3)*4:4] or i)
#It's multiplied by 4 so that if it isn't a mutliple of 3 it tries to print
#"FizzBuzz"[4:4] which is blank, so it print i instead.

A similar method can be done with multiples of 5

(i^4)%5

And to make this a functional FizzBuzz we need to convert 0 into 8 and 1 into 4 by:

8 - ((-i^4)%5)

This is now a functional FizzBuzz in python:

for i in range(1,101):
    print("FizzBuzz"[((i*i)%3)*4:8 - ((-i**4)%5)] or i)

I have discovered there is a way to get a 0 or a 1 depending on whether a number is a multiple of a desired number like this:

result = (number ^ (desired_number - 1)) % desired_number

But this rule only works for prime numbers and if you tried this with any other number the entire idea falls apart. Can a similar function be made for non-primes or is this something that applies to primes only?


Solution

  • This is indeed the small theorem of Fermat.

    There is a generalization using Eulers Totient function phi in that

    a^phi(m) ==1 mod m
    

    if a and m are relatively prime.

    As phi(15)=phi(3)*phi(5)=(3-1)*(5-1)=8, the remainders of a^8 mod 15 for a=0,1,2,...,14 are

    0,1,1,6,1,10,6,1,1,6,10,1,6,1,1.