Brute force
The first step is to identify curious faction, such as \( \frac{49}{98} \). A Curious faction can take one of four forms, which can be expressed as follows:
\[ \frac{ax}{bx} = \frac{a}{b} \Rightarrow \frac{10a + x}{10b + x} = \frac{a}{b} \Rightarrow 10ab + bx = 10ab + ax \Rightarrow x(a - b) = 0 \]
This implies that either \( x = 0 \) or \( a = b \). Both solutions are trivial.
\[ \frac{xa}{xb} = \frac{a}{b} \Rightarrow \frac{10x + a}{10x + b} = \frac{a}{b} \Rightarrow 10bc + ba = 10ax + ab \Rightarrow x(a - b) = 0 \]
This yields the same trivial solutions as the first case.
The only non-trivial solutions are of the form \( \frac{ax}{xb} \) or \( \frac{xa}{bx} \). We simply need to determine whether we are dealing with the first or second case and verify whether the fractions are the same with and without \( x \).
From solution1.py:
def is_curious_fraction(numerator, denominator):
if numerator % 10 == denominator // 10:
return abs((numerator / denominator) - (numerator // 10 / (denominator % 10))) < 0.0000001
elif numerator // 10 == denominator % 10:
return abs((numerator / denominator) - (numerator % 10 / (denominator // 10))) < 0.0000001
return False
To ensure accuracy in the presence of floating-point values, the returned value must be compared to a small value to ensure it is close enough to zero.
The second step is to iterate over every fraction, with the numerator being smaller than the denominator, as all fractions must be smaller than 1.
From solution1.py:
def digit_cancelling_fractions():
final_numerator, final_denominator = 1, 1
for numerator in range(10, 100):
for denominator in range(numerator + 1, 100):
if numerator % 10 == 0 or denominator % 10 == 0:
continue
if is_curious_fraction(numerator, denominator):
final_numerator *= numerator
final_denominator *= denominator
return final_denominator // gcd(final_numerator, final_denominator)