import math from e057 import add_fractions def get_floor_sqrt(n): return math.floor(math.sqrt(n)) def next_expansion_1(current_a, current_nominator, current_denominator, original_number): cn = current_nominator cd = current_denominator cn, cd = cd, (original_number - cd * cd) // cn next_a = math.floor((math.sqrt(original_number) + cn) // cd) 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_1(a, cd, cn, n) sequence.append(a) sequence.pop() return ((floor_sqrt), sequence) def next_expansion_2(previous_numerator, previous_denumerator, value): if previous_numerator == 0: return (value, 1) return add_fractions(previous_denumerator, previous_numerator, value, 1) def get_fractions(n, x): # print("get_fractions(n={}, x={})".format(n, x)) # Get sequence of a_x first_value, sequence = get_continued_fraction_sequence(n) sequence = [first_value] + math.ceil(x / len(sequence)) * sequence sequence = sequence[:x + 1] sequence = sequence[::-1] n, d = 0, 1 for s in sequence: n, d = next_expansion_2(n, d, s) return (n, d) def get_minimal_solution(d): for i in range(0, 100): x, y = get_fractions(d, i) if x * x - d * y * y == 1: return((x, y)) def is_square(n): return math.sqrt(n).is_integer() def euler_066(): # XXX: This seems really long and complicated. We can do better. x_max = 0 d_max = 0 for d in range(2, 1001): if is_square(d): continue x, y = get_minimal_solution(d) if x > x_max: x_max = x d_max = d print("d: {} x: {}".format(d_max, x_max)) s = d_max return s if __name__ == "__main__": print("e066.py: " + str(euler_066())) assert(euler_066() == 661)