"""
David Pratt
for SIAM Fall 2019

========================= PROJECT EULER #02 ============================

Each new term in the Fibonacci sequence is generated by adding the
previous two terms. By starting with 1 and 2, the first 10 terms will be

    1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.

========================================================================

The strategy is to implement a generator function that yields the
Fibonacci numbers. We will iterate over the Fibonacci numbers, summing
the even terms until we see a Fibonacci number larger than four million.

"""

def fib():
    """
    Generates all Fibonacci numbers. Note here that the 0th index
    Fibonacci number is 1, the 1st index is 2, etc.

    Example:
        >>> for i, f in enumerate(fib()):
                print(i, f)
                if i > 10: break
        0 1
        1 2
        2 3
        3 5
        4 8
        5 13
        6 21
        7 34
        8 55
        9 89
        10 144
        11 233
    """
    # set small_fib = 1 and big_fib = 1
    small_fib, big_fib = 1, 1
    while True:
        small_fib, big_fib = big_fib, small_fib + big_fib
        yield small_fib


def main():
    LIMIT = 4e6
    fib_sum = 0

    for f in fib():
        if f > LIMIT:
            return fib_sum
        fib_sum += f if f % 2 == 0 else 0


if __name__ == '__main__':
    # runtime ~ 5.06 microseconds
    ans = main()
    print(ans)
