132 lines
3.4 KiB
Python
132 lines
3.4 KiB
Python
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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|