euler/python/e100.py

48 lines
1.5 KiB
Python
Raw Normal View History

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)