#!/usr/bin/env python3
"""Even Fibonacci Numbers
Project Euler, Problem 2
http://projecteuler.net/problem=2

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.
"""
from e001 import bounded


def sum_even_fibs_with_values_below(n):
    """Sums all even-valued Fibonacci numbers with values below n.
    >>> sum_even_fibs_with_values_below(55) == sum([2, 8, 34]) == 44
    True
    """
    return sum(bounded(even(fibs()), n))


def even(l):
    """Collects the even-valued elements of a list l.
    >>> [i for i in even(range(10))]
    [0, 2, 4, 6, 8]
    """
    return filter(is_even, l)


def is_even(n):
    """Returns True if an integer is even.
    >>> [is_even(i) for i in range(1, 6)]
    [False, True, False, True, False]
    """
    return not n & 1


def fibs(a=1, b=1):
    """Generates Fibonacci numbers.
    >>> from itertools import islice
    >>> [i for i in islice(fibs(), 11)]
    [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    """
    while True:
        yield a
        a, b = b, a + b


def main():
    print(sum_even_fibs_with_values_below(4000000))


if __name__ == "__main__":
    import doctest
    doctest.testmod()
    main()
