Objective
Given a positive reduced fraction, output its parent in the Stern-Brocot tree. The outputted fraction shall also be reduced.
The Stern-Brocot tree
The Stern-Brocot tree is a infinite-height complete binary (search) tree that accommodates every positive reduced fraction exactly once. It is defined as follows:
- \$1/1\$ is the root.
- For every positive reduced fraction \$n/d\$, its left child is \$(n+n')/(d+d')\$ provided that \$n'/d'\$ is the biggest smaller ancestor of \$n/d\$, or \$n/(d+1)\$ if there's no such ancestor.
- Likewise, for every positive reduced fraction \$n/d\$, its right child is \$(n+n')/(d+d')\$ provided that \$n'/d'\$ is the smallest bigger ancestor of \$n/d\$, or \$(n+1)/d\$ if there's no such ancestor.
For illustrative purposes, here's the few shallowest entries of the Stern-Brocot tree:
Since \$1/1\$ doesn't have a parent, it is considered to be an invalid input.
Examples
Input -> Output
1/2 -> 1/1
2/1 -> 1/1
3/7 -> 2/5
4/7 -> 3/5
7/3 -> 5/2
7/4 -> 5/3
1/16 -> 1/15
16/1 -> 15/1
53/72 -> 39/53
Ungolfed Solution (Haskell)
import Data.Ratio
findParent :: Rational -> Rational
findParent x
| x <= 0 = error "Nonpositive input"
| otherwise = go 1 1 (0,1) (1,0) where
go :: Rational -> Rational -> (Integer, Integer) -> (Integer, Integer) -> Rational
go y z l@(ln, ld) r@(rn, rd) = case compare x z of
EQ -> y
LT -> go z ((numerator z + ln) % (denominator z + ld)) l (numerator z, denominator z)
GT -> go z ((numerator z + rn) % (denominator z + rd)) (numerator z, denominator z) r