2019-07-18 20:23:44 +02:00
|
|
|
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)
|
|
|
|
|
2019-07-18 03:29:59 +02:00
|
|
|
|
|
|
|
def euler_064():
|
2019-07-18 20:23:44 +02:00
|
|
|
s = len([n for n in range(1, 10001) if get_period(n) % 2 != 0])
|
|
|
|
return s
|
2019-07-18 03:29:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
print("e064.py: " + str(euler_064()))
|
2019-07-18 20:23:44 +02:00
|
|
|
assert(euler_064() == 1322)
|