#fraccion: numerador(int) denominador(int)
import estructura
estructura.crear("fraccion","numerador denominador")

#esFraccion: fraccion -> bool
#True si x es una fraccion valida
#ej: esFraccion(fraccion(1,2))->True
#ej: esFraccion(fraccion(1,0))->False
def esFraccion(x):
    return type(x)==fraccion \
       and type(x.numerador)==int \
       and type(x.denominador)==int \
       and x.denominador!=0
assert esFraccion(fraccion(1,2))
assert not esFraccion(fraccion(1,0))

#fracciones para probar operaciones aritméticas
f1=fraccion(1,2)
f2=fraccion(3,4)

#sumar: fraccion fraccion -> fraccion
# x + y
#ej: sumar(f1,f2)->fraccion(10,8)
def sumar(x,y):
  assert esFraccion(x)
  assert esFraccion(y)
  a = x.numerador   * y.denominador + \
      x.denominador * y.numerador
  b = x.denominador * y.denominador
  return fraccion(a,b)
assert sumar(f1,f2)==fraccion(10,8)

#restar: fraccion fraccion -> fraccion
# x - y
#ej: restar(f1,f2)->fraccion(-2,8)
def restar(x,y):
  assert esFraccion(x)
  assert esFraccion(y)
  a = x.numerador   * y.denominador - \
      x.denominador * y.numerador
  b = x.denominador * y.denominador
  return fraccion(a,b)
assert restar(f1,f2)==fraccion(-2,8)

#multiplicar: fraccion fraccion -> fraccion
# x * y
#ej: multiplicar(f1,f2)->fraccion(3,8)
def multiplicar(x,y):
  assert esFraccion(x)
  assert esFraccion(y)
  a = x.numerador   * y.numerador
  b = x.denominador * y.denominador
  return fraccion(a,b)
assert multiplicar(f1,f2)==fraccion(3,8)

#dividir: fraccion fraccion -> fraccion
# x / y
#ej: dividir(f1,f2)->fraccion(4,6)
def dividir(x,y):
  assert esFraccion(x)
  assert esFraccion(y)
  a = x.numerador   * y.denominador
  b = x.denominador * y.numerador
  assert b != 0
  return fraccion(a,b)
assert dividir(f1,f2)== fraccion(4,6)

from mcd import *
#simplificar: fraccion -> fraccion
#fraccion con valor de fraccion x simplificada
#ej: simplificar(fraccion(2,4))->fraccion(1,2)
def simplificar(x):
  assert esFraccion(x)
  m=mcd(abs(x.numerador),abs(x.denominador))
  return fraccion(x.numerador//m, x.denominador//m)
assert simplificar(fraccion(2,4))==fraccion(1,2)

#esIgual: fraccion fraccion -> bool
#True si x es igual a y
#ej: esIgual(fraccion(1,2),fraccion(2,4)) -> True
#    esIgual(fraccion(1,2),fraccion(1,3)) -> False
def esIgual(x,y):
    assert esFraccion(x)
    assert esFraccion(y)
    return simplificar(x)==simplificar(y)
assert esIgual(fraccion(1,2),fraccion(2,4))
assert not esIgual(fraccion(1,2),fraccion(1,3)) 

#comparar: fraccion fraccion -> int
#0 si x=y, n°<0 si x<y, n°>0 si x>y
#ej: comparar(fraccion(1,2),fraccion(1,3)) -> n°>0
#ej: comparar(fraccion(1,3),fraccion(1,2)) -> n°<0
#ej: comparar(fraccion(1,2),fraccion(2,4)) -> 0
def comparar(x,y):
  assert esFraccion(x)
  assert esFraccion(y)
  return x.numerador * y.denominador - x.denominador * y.numerador
assert comparar(fraccion(1,2),fraccion(1,3)) > 0
assert comparar(fraccion(1,3),fraccion(1,2)) < 0
assert comparar(fraccion(1,2),fraccion(2,4)) == 0

#leer: str str -> fraccion
#fraccion con numerador y denominador que se leen con preguntas x e y
#ej: leer("a?","b?")->fraccion(1,2) si lee 1 y 2
def leer(x="numerador?",y="denominador?"):
    a=int(input(x))
    b=int(input(y))
    assert b != 0
    return fraccion(a,b)
#assert leer("a?","b?")==fraccion(1,2)

#escribir: str fraccion ->
#escribe x seguido de numerador / denominador de y
#ej: escribir("f:",fraccion(1,2)) escribe "f: 1 / 2"
def escribir(x,y):
    assert type(x)==str
    assert esFraccion(y)
    print(x,y.numerador,"/",y.denominador)
#escribir("f:",fraccion(1,2))


