import math


def get_floor_sqrt(n):
    return math.floor(math.sqrt(n))


def next_expansion(current_a, current_nominator,
                   current_denominator, original_number):
    # Less typing
    cn = current_nominator
    cd = current_denominator

    # Step 1: Multiply the fraction so that we can use the third binomial
    # formula. Make sure we can reduce the nominator.
    assert((original_number - cd * cd) % cn == 0)
    # The new nominator is the denominator since we multiply with (x + cd) and
    # then reduce the previous nominator. The new denominator is calculated by
    # applying the third binomial formula and then by divided by the previous
    # nominator.
    cn, cd = cd, (original_number - cd * cd) // cn

    # Step 2: Calculate the next a by finding the next floor square root.
    next_a = math.floor((math.sqrt(original_number) + cn) // cd)

    # Step 3: Remove next a from the fraction by substracting it.
    cn = cn - next_a * cd
    cn *= -1

    return next_a, cn, cd


def get_continued_fraction_sequence(n):

    # If number is a square number we return it.
    floor_sqrt = get_floor_sqrt(n)
    if n == floor_sqrt * floor_sqrt:
        return ((floor_sqrt), [])

    # Otherwise, we calculate the next expansion till we
    # encounter a step a second time.
    a = floor_sqrt
    cn = a
    cd = 1
    sequence = []
    previous_steps = []

    while not (a, cn, cd) in previous_steps:
        # print("a: {} cn: {} cd: {}".format(a, cn, cd))
        previous_steps.append((a, cn, cd))
        a, cn, cd = next_expansion(a, cd, cn, n)
        sequence.append(a)
    sequence.pop()
    return ((floor_sqrt), sequence)


def get_period(n):
    _, sequence = get_continued_fraction_sequence(n)
    return len(sequence)


def euler_064():
    s = len([n for n in range(1, 10001) if get_period(n) % 2 != 0])
    return s


if __name__ == "__main__":
    print("e064.py: " + str(euler_064()))
    assert(euler_064() == 1322)
