# Multi-pass FizzBuzz
n = 100
# [['1'], ['2'], ['3'], ['4'], ['5'], ...]
seq = [[str(i)] for i in range(1, n + 1)]
# [['1'], ['2'], ['3', 'Fizz'], ['4'], ['5'], ...]
for i in range(3, n + 1, 3):
seq[i-1].append('Fizz')
# [['1'], ['2'], ['3', 'Fizz'], ['4'], ['5', 'Buzz'], ..., ['15', ''Fizz', 'Buzz'], ...]
for i in range(5, n + 1, 5):
seq[i-1].append('Buzz')
# Arithmetic equivalent to:
# len=1 -> the whole thing (from zero to end, because zero = -zero)
# len=2 -> the length-1 suffix (just Fizz or Buzz)
# len=3 -> the length-2 suffix (Fizz and Buzz)
# The branch is hidden in the slice syntax:
# Python has to check whether `x` is negative in `terms[x:]`.
for terms in seq:
print(''.join(terms[-(len(terms) - 1):]))
Here's a version that uses generators instead of multiple passes over a list:
# Single-pass FizzBuzz
n = 100
def numbers():
for i in range(1, n+1):
yield [str(i)]
def fizzies():
nums = numbers()
try:
while True:
yield next(nums)
yield next(nums)
yield [*next(nums), 'Fizz']
except StopIteration:
pass
def buzzies():
fzs = fizzies()
try:
while True:
yield next(fzs)
yield next(fzs)
yield next(fzs)
yield next(fzs)
yield [*next(fzs), 'Buzz']
except StopIteration:
pass
for terms in buzzies():
print(''.join(terms[-(len(terms) - 1):]))
Edit: Can't resist -- unbounded without loops, but recursion blows the call stack (granted, well after 100):