# Principled Programming / Tim Teitelbaum / Chapter 18.
from fraction import Fraction

class Rational(Fraction):
    # Constructor.
    def __init__(self, numerator: int, denominator: int):
        super().__init__(numerator, denominator)    # Apply the Fraction constructor.
        if numerator == 0:
            self._value = 1
        else:
            sign: int = +1
            g: int = gcd(abs(numerator), abs(denominator))
            if ((numerator < 0) and (denominator > 0)) or (
                (numerator > 0) and (denominator < 0) ): sign = -1
            self._key   = sign * abs(numerator) // g
            self._value = abs(denominator) // g

    # String representation of self.
    def __str__(self) -> str:
        if self._value == 1: return str(self._key)  # self as an integer
        else: return super().__str__()                  # self as Fraction

def gcd(x:int, y:int) -> int:
    """# Given x>0 and y>0, return the greatest common divisor of x and y."""
    while x != y:
        if x > y:
            x = x - y
        else:
            y = y - x
    return x