"""
 fizzbuzz.py

 Playing around with the Fizz Buzz coding task;
 see for example http://wiki.c2.com/?FizzBuzzTest .

 tested with python 3.5

 Jim Mahoney | cs.marlboro.college | Oct 31 2018 | MIT License
"""

# -----------------------------------
# with functions
print("-- functions --")

def divides(small, big):
    """ return True if big / small is an integer,
        i.e. if small goes into big an integer number of times
        i.e. if small divides big """
    return big % small == 0

def fizzbuzz(i):
    """ Return 'Fizz', 'Buzz', 'FizzBuzz', or i
        depending on whether i is divisible by 3, 5, both, or neither. """
    if divides(3, i) and divides(5, i):
        return 'FizzBuzz'
    if divides(3, i):
        return 'Fizz'
    if divides(5, i):
        return 'Buzz'
    return str(i)

for i in range(1,101):
    print(fizzbuzz(i))

# -------------------------------------------------
# imperitive coding style
print("-- imperitive --")

# ... taking advantage of "or"'s shortcircuit trick, from
# http://codereview.stackexchange.com/questions/9751/ultra-beginner-python-fizzbuzz-am-i-missing-something

for i in range(1,101):
    msg = ''
    if i % 3 == 0:
        msg = msg + 'Fizz'
    if i % 5 == 0:
        msg = msg + 'Buzz'
    print(msg or i)

# -------------------------------------
# with objects
print("-- objects --")

class FBInt:
    """ An integer i that as a string is 
        'Fizz', 'Buzz', 'FizzBuzz', or str(i). """
    def __init__(self, i):
        self.i = i
    def __str__(self):
        result = ''
        if self.i % 3 == 0:
            result = result = 'Fizz'
        if self.i % 5 == 0:
            result = result = 'Buzz'
        if result:
            return result
        else:
            return str(self.i)

class FizzBuzz:
    """ A looper for the FizzBuzz problem """
    def __init__(self, low=1, high=100):
        self.low = low
        self.high = high
    def __str__(self):
        result = ''
        for i in range(self.low, self.high + 1):
            result = result + str(FBInt(i)) + "\n"
        return result

print(FizzBuzz(1, 100))

# -----------------------------------------------------
# in a functional programming style
# ... using the previously defined fizzbuzz() function
# ... and "map"

print("-- functional --")

def to_lines(word_list):
    """ join a list of words into a string of lines """
    return '\n'.join(word_list)

print(
  to_lines(
    map( str,
      map( fizzbuzz,
        range(1, 100)))))