from fractions import Fraction def euler_100(): F_ONE_HALF = Fraction(1, 2) prev_blue_discs, blue_discs = 10, 10 while True: # Brute force search blue discs blue_discs += 1 # Binary search red discs red_upper = blue_discs // 2 red_lower = 1 while red_upper != red_lower: red_discs = red_lower + (red_upper - red_lower) // 2 total_discs = blue_discs + red_discs f1 = Fraction(blue_discs, total_discs) f2 = Fraction(blue_discs - 1, total_discs - 1) f = f1 * f2 if f == F_ONE_HALF: # End criterion by Euler Problem if total_discs > 10**12: return blue_discs # The ration between two solutions seems to be constant so we # can get the next larger candidate for blue_discs much # quicker. ratio = blue_discs / prev_blue_discs # print("blue_discs={} ratio={}".format(blue_discs, ratio)) prev_blue_discs = blue_discs blue_discs = int(blue_discs * ratio) break elif f < F_ONE_HALF: red_upper = red_discs else: red_lower = red_discs # No solution for current number of blue discs if abs(red_upper - red_lower) <= 1: break if __name__ == "__main__": solution = euler_100() print("e100.py: " + str(solution)) assert(solution == 756872327473)