Project Euler Problem 71 Solution

Project Euler Problem 71 Solution

Ordered Fractions

by {BetaProjects} | Project Euler & HackerRank
Difficulty: Medium

Project Euler Problem 71 Statement

Consider the fraction, $\dfrac n d$, where $n$ and $d$ are positive integers. If $n \lt d$ and $\operatorname{HCF}(n,d)=1$, it is called a reduced proper fraction.

If we list the set of reduced proper fractions for $d \le 8$ in ascending order of size, we get: $$\frac 1 8, \frac 1 7, \frac 1 6, \frac 1 5, \frac 1 4, \frac 2 7, \frac 1 3, \frac 3 8, \mathbf{\frac 2 5}, \frac 3 7, \frac 1 2, \frac 4 7, \frac 3 5, \frac 5 8, \frac 2 3, \frac 5 7, \frac 3 4, \frac 4 5, \frac 5 6, \frac 6 7, \frac 7 8$$

It can be seen that $\dfrac 2 5$ is the fraction immediately to the left of $\dfrac 3 7$.

By listing the set of reduced proper fractions for $d \le 1\,000\,000$ in ascending order of size, find the numerator of the fraction immediately to the left of $\dfrac 3 7$.

Solution

Rephrasing the problem

Project Euler Problem 71 involves finding fractions between 0 and 1 that are closest to a given fraction \( \frac{a}{b} \) with denominators up to \( n \). The goal is to identify the fraction \( \frac{c}{d} \) such that:

for _ in range(int(input())):
    a, b, n = map(int, input().split())
    ln, ld, rn, rd = 0, 1, 1, 1
    while ld + rd <= n:
        mn, md = ln + rn, ld + rd
        if a * md < b * mn:
            rn, rd = mn, md
        elif a == mn and b == md:
            nums = (n - ld - b) // b
            ln += a * nums
            ld += b * nums
            rn, rd = mn, md
        else:
            ln, ld = mn, md
    print(ln, ld)
Variables Explained
Solving Method
  1. Initialization:

    Start with two boundary fractions: \( \frac{0}{1} \) (left) and \( \frac{1}{1} \) (right).

  2. While Loop:

    The loop continues as long as the sum of the denominators \( ld + rd \) does not exceed \( n \). In each iteration, compute the middle fraction \( \frac{mn}{md} = \frac{ln + rn}{ld + rd} \).

  3. Comparing Fractions:
    • Condition 1: If \( a \times md < b \times mn \), it implies \( \frac{a}{b} < \frac{mn}{md} \). Hence, update the right fraction to the middle fraction.
    • Condition 2: If \( a == mn \) and \( b == md \), perform an optimization to jump ahead by calculating how many times the denominator can be incremented by \( b \) without exceeding \( n \).
    • Else: Update the left fraction to the middle fraction since \( \frac{mn}{md} \) is less than \( \frac{a}{b} \).
  4. Termination:

    Once \( ld + rd > n \), the loop terminates, and the closest fraction \( \frac{ln}{ld} \) is printed.

Step-by-Step Walkthrough

Let's walk through an example to illustrate how the script operates.

Example Input

1
3 7 8

Initial State

Iteration 1

Iteration 2

Iteration 3

Iteration 4

Termination

HackerRank version

HackerRank Project Euler 71: By listing the set of reduced proper fractions for $d\le N$ in ascending order of size, find the numerator and denominator of the fraction immediately to the left of $\frac{a}{b}$.

Python Source Code

for _ in range(int(input())):
    a, b, n = map(int, input().split())
    ln, ld, rn, rd = 0, 1, 1, 1
    while ld + rd <= n:
        mn, md = ln + rn, ld + rd
        if a * md < b * mn:
            rn, rd = mn, md
        elif a == mn and b == md:
            nums = (n - ld - b) // b
            ln += a * nums
            ld += b * nums
            rn, rd = mn, md
        else:
            ln, ld = mn, md
    print(ln, ld)