from __future__ import annotations from typing import Iterable, Generator from tools import gcd class Fractions: """ Should represent a fraction not a division """ __slots__ = ['num', 'den'] __match_args__ = ("num", "den") #todo check if num and den are part of a domain, so a/b as a meaning a gcd work well #todo implement __iadd__ etc... if performance needed def __init__(self, *args): match args: case num, den: self.num = num self.den = den case x, : self.num = x self.den = 1 def __repr__(self): return f'Fractions({self.num}, {self.den})' def simplify_gcd(self): """Simplify fraction by diving num and den by their gcd return None""" match self.num, self.den: case int(num), int(den): gcd_ = gcd(num, den) self.num //= gcd_ self.den //= gcd_ # can be completed with others objects that support gcd like polynomials etc... def simplify_to_num(self): """from frac(a, 1) return a.""" if self.den == 1: return self.num def simplify_nested(self, rec=True): """simplify nested fractions. Fractions(1, Fractions(1, Fractions(1, Fractions(1, 2)))) -> Fractions(2, 1) For one simplification step put rec=False return None""" def aux(fract): match fract: case Fractions(Fractions(a, b), Fractions(c, d)): fract.num = a * d fract.den = b * c case Fractions(num, Fractions(a, b)): fract.num = num * b fract.den = a case Fractions(Fractions(a, b), den): fract.num = a fract.den = b * den if rec: num, den = self.num, self.den if isinstance(num, Fractions) or isinstance(den, Fractions): aux(fract) aux(self) def simplify_all_(self): self.simplify_gcd() self.simplify_nested() res = self.simplify_to_num() if res: return res return self def __add__(self, other): match other: case int(x): return Fractions(self.num + self.den*x, self.den) case Fractions(num, den): result = Fractions(self.num*den + num*self.den, self.den*den) return result return ValueError def __radd__(self, other): return other + self def __neg__(self): return Fractions(-self.num, self.den) def __mul__(self, other): match other: case int(x): return Fractions(self.num*x, self.den) case Fractions(num, den): result = Fractions(self.num*num, self.den*den) return result return ValueError def __rmul__(self, other): return self*other def __truediv__(self, other): match other: case int(x): return Fractions(self.num, self.den*x) case Fractions(num, den): return Fractions(self.num*den, self.den*num) def __rtruediv__(self, other): res = self/other return Fractions(res.den, res.num) if __name__ == "__main__": a = Fractions(1, 2) a += 1 print(a)