Esta semana he publicado en Exercitium las soluciones de los siguientes problemas sobre el TAD (tipo abstracto de datos) de los polinomios.
- 1. Construcción de términos
- 2. Término líder de un polinomio
- 3. Suma de polinomios
- 4. Producto de polinomios
- 5. Valor de un polinomio en un punto
A continuación se muestran las soluciones.
1. Construcción de términos
Usando el tipo abstracto de los polinomios, definir la función
creaTermino :: (Num a, Eq a) => Int -> a -> Polinomio a |
tal que creaTermino n a
es el término a·x^n
. Por ejemplo,
creaTermino 2 5 == 5*x^2 |
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
import TAD.Polinomio (Polinomio, polCero, consPol) creaTermino :: (Num a, Eq a) => Int -> a -> Polinomio a creaTermino n a = consPol n a polCero |
from typing import TypeVar from hypothesis import given from hypothesis import strategies as st from src.TAD.Polinomio import (Polinomio, consPol, polCero) A = TypeVar('A', int, float, complex) # 1ª solución # =========== def creaTermino(n: int, a: A) -> Polinomio[A]: return consPol(n, a, polCero()) # 2ª solución # =========== def creaTermino2(n: int, a: A) -> Polinomio[A]: r: Polinomio[A] = polCero() return r.consPol(n, a) # Equivalencia de las definiciones # ================================ # La propiedad es @given(st.integers(min_value=0, max_value=9), st.integers(min_value=-9, max_value=9)) def test_creaTermino(n: int, a: int) -> None: assert creaTermino(n, a) == creaTermino2(n, a) # La comprobación es # > poetry run pytest -q Pol_Crea_termino.py # 1 passed in 0.21s |
2. Término líder de un polinomio
Usando el tipo abstracto de los polinomios, definir la función
termLider :: (Num a, Eq a) => Polinomio a -> Polinomio a |
tal que termLider p
es el término líder del polinomio p
. Por ejemplo,
λ> ejPol = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero)) λ> ejPol x^5 + 5*x^2 + 4*x λ> termLider ejPol x^5 |
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
import TAD.Polinomio (Polinomio, coefLider, grado, polCero, consPol) import Pol_Crea_termino (creaTermino) termLider :: (Num a, Eq a) => Polinomio a -> Polinomio a termLider p = creaTermino (grado p) (coefLider p) -- La función creaTermino está definida en el ejercicio -- "Construcción de términos" que se encuentra en -- https://bit.ly/3GXteuH |
from typing import TypeVar from hypothesis import given from src.Pol_Crea_termino import creaTermino from src.TAD.Polinomio import (Polinomio, coefLider, consPol, grado, polCero, polinomioAleatorio) A = TypeVar('A', int, float, complex) # 1ª solución # =========== def termLider(p: Polinomio[A]) -> Polinomio[A]: return creaTermino(grado(p), coefLider(p)) # 2ª solución # =========== def termLider2(p: Polinomio[A]) -> Polinomio[A]: return creaTermino(p.grado(), p.coefLider()) # La función creaTermino está definida en el ejercicio # "Construcción de términos" que se encuentra en # https://bit.ly/3GXteuH # Equivalencia de las definiciones # ================================ # La propiedad es @given(p=polinomioAleatorio()) def test_termLider(p: Polinomio[int]) -> None: assert termLider(p) == termLider2(p) # La comprobación es # > poetry run pytest -q Pol_Termino_lider.py # 1 passed in 0.21s |
3. Suma de polinomios
Usando el tipo abstracto de los polinomios, definir la función
sumaPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a |
tal que (sumaPol p q) es la suma de los polinomios p y q. Por ejemplo,
λ> ejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero)) λ> ejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero)) λ> ejPol1 3*x^4 + -5*x^2 + 3 λ> ejPol2 x^5 + 5*x^2 + 4*x λ> sumaPol ejPol1 ejPol2 x^5 + 3*x^4 + 4*x + 3 |
Comprobar con QuickCheck las siguientes propiedades:
polCero
es el elemento neutro de la suma.- la suma es conmutativa.
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
import TAD.Polinomio (Polinomio, polCero, esPolCero, consPol, grado, coefLider, restoPol) import Test.QuickCheck sumaPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a sumaPol p q | esPolCero p = q | esPolCero q = p | n1 > n2 = consPol n1 a1 (sumaPol r1 q) | n1 < n2 = consPol n2 a2 (sumaPol p r2) | otherwise = consPol n1 (a1+a2) (sumaPol r1 r2) where (n1, a1, r1) = (grado p, coefLider p, restoPol p) (n2, a2, r2) = (grado q, coefLider q, restoPol q) -- Propiedad. El polinomio cero es el elemento neutro de la suma. prop_neutroSumaPol :: Polinomio Int -> Bool prop_neutroSumaPol p = sumaPol polCero p == p -- Comprobación con QuickCheck. -- λ> quickCheck prop_neutroSumaPol -- OK, passed 100 tests. -- Propiedad. La suma es conmutativa. prop_conmutativaSuma :: Polinomio Int -> Polinomio Int -> Bool prop_conmutativaSuma p q = sumaPol p q == sumaPol q p -- Comprobación: -- λ> quickCheck prop_conmutativaSuma -- OK, passed 100 tests. |
from typing import TypeVar from hypothesis import given from src.TAD.Polinomio import (Polinomio, coefLider, consPol, esPolCero, grado, polCero, polinomioAleatorio, restoPol) A = TypeVar('A', int, float, complex) # 1ª solución # =========== def sumaPol(p: Polinomio[A], q: Polinomio[A]) -> Polinomio[A]: if esPolCero(p): return q if esPolCero(q): return p n1, a1, r1 = grado(p), coefLider(p), restoPol(p) n2, a2, r2 = grado(q), coefLider(q), restoPol(q) if n1 > n2: return consPol(n1, a1, sumaPol(r1, q)) if n1 < n2: return consPol(n2, a2, sumaPol(p, r2)) return consPol(n1, a1 + a2, sumaPol(r1, r2)) # 2ª solución # =========== def sumaPol2(p: Polinomio[A], q: Polinomio[A]) -> Polinomio[A]: if p.esPolCero(): return q if q.esPolCero(): return p n1, a1, r1 = p.grado(), p.coefLider(), p.restoPol() n2, a2, r2 = q.grado(), q.coefLider(), q.restoPol() if n1 > n2: return sumaPol(r1, q).consPol(n1, a1) if n1 < n2: return sumaPol(p, r2).consPol(n2, a2) return sumaPol(r1, r2).consPol(n1, a1 + a2) # Equivalencia de las definiciones # ================================ # La propiedad es @given(p=polinomioAleatorio(), q=polinomioAleatorio()) def test_sumaPol(p: Polinomio[int], q: Polinomio[int]) -> None: assert sumaPol(p, q) == sumaPol2(p,q) # Propiedad. El polinomio cero es el elemento neutro de la suma. @given(p=polinomioAleatorio()) def test_neutroSumaPol(p: Polinomio[int]) -> None: assert sumaPol(polCero(), p) == p assert sumaPol(p, polCero()) == p # -- Propiedad. La suma es conmutativa. @given(p=polinomioAleatorio(), q=polinomioAleatorio()) def test_conmutativaSuma(p: Polinomio[int], q: Polinomio[int]) -> None: assert sumaPol(p, q) == sumaPol(q, p) # La comprobación es # > poetry run pytest -v Pol_Suma_de_polinomios.py # test_sumaPol PASSED # test_neutroSumaPol PASSED # test_conmutativaSuma PASSED |
4. Producto de polinomios
Usando el tipo abstracto de los polinomios, definir la función
multPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a |
tal que multPol p q
es el producto de los polinomios p
y q
. Por ejemplo,
λ> ejPol1 = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero)) λ> ejPol2 = consPol 5 1 (consPol 2 5 (consPol 1 4 polCero)) λ> ejPol1 3*x^4 + -5*x^2 + 3 λ> ejPol2 x^5 + 5*x^2 + 4*x λ> multPol ejPol1 ejPol2 3*x^9 + -5*x^7 + 15*x^6 + 15*x^5 + -25*x^4 + -20*x^3 + 15*x^2 + 12*x |
Comprobar con QuickCheck las siguientes propiedades
- El producto de polinomios es conmutativo.
- El producto es distributivo respecto de la suma.
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
import TAD.Polinomio (Polinomio, polCero, esPolCero, consPol, grado, coefLider, restoPol) import Pol_Termino_lider (termLider) import Pol_Suma_de_polinomios (sumaPol) import Test.QuickCheck multPol :: (Num a, Eq a) => Polinomio a -> Polinomio a -> Polinomio a multPol p q | esPolCero p = polCero | otherwise = sumaPol (multPorTerm (termLider p) q) (multPol (restoPol p) q) -- (multPorTerm t p) es el producto del término t por el polinomio -- p. Por ejemplo, -- ejTerm == 4*x -- ejPol2 == x^5 + 5*x^2 + 4*x -- multPorTerm ejTerm ejPol2 == 4*x^6 + 20*x^3 + 16*x^2 multPorTerm :: (Num t, Eq t) => Polinomio t -> Polinomio t -> Polinomio t multPorTerm term pol | esPolCero pol = polCero | otherwise = consPol (n+m) (a*b) (multPorTerm term r) where n = grado term a = coefLider term m = grado pol b = coefLider pol r = restoPol pol -- El producto de polinomios es conmutativo. prop_conmutativaProducto :: Polinomio Int -> Polinomio Int -> Bool prop_conmutativaProducto p q = multPol p q == multPol q p -- La comprobación es -- λ> quickCheck prop_conmutativaProducto -- OK, passed 100 tests. -- El producto es distributivo respecto de la suma. prop_distributivaProductoSuma :: Polinomio Int -> Polinomio Int -> Polinomio Int -> Bool prop_distributivaProductoSuma p q r = multPol p (sumaPol q r) == sumaPol (multPol p q) (multPol p r) -- Comprobación: -- λ> quickCheck prop_distributivaProductoSuma -- OK, passed 100 tests. |
from typing import TypeVar from hypothesis import given from src.Pol_Suma_de_polinomios import sumaPol from src.Pol_Termino_lider import termLider from src.TAD.Polinomio import (Polinomio, coefLider, consPol, esPolCero, grado, polCero, polinomioAleatorio, restoPol) A = TypeVar('A', int, float, complex) # multPorTerm(t, p) es el producto del término t por el polinomio # p. Por ejemplo, # ejTerm == 4*x # ejPol2 == x^5 + 5*x^2 + 4*x # multPorTerm ejTerm ejPol2 == 4*x^6 + 20*x^3 + 16*x^2 def multPorTerm(term: Polinomio[A], pol: Polinomio[A]) -> Polinomio[A]: n = grado(term) a = coefLider(term) m = grado(pol) b = coefLider(pol) r = restoPol(pol) if esPolCero(pol): return polCero() return consPol(n + m, a * b, multPorTerm(term, r)) def multPol(p: Polinomio[A], q: Polinomio[A]) -> Polinomio[A]: if esPolCero(p): return polCero() return sumaPol(multPorTerm(termLider(p), q), multPol(restoPol(p), q)) # El producto de polinomios es conmutativo. @given(p=polinomioAleatorio(), q=polinomioAleatorio()) def test_conmutativaProducto(p: Polinomio[int], q: Polinomio[int]) -> None: assert multPol(p, q) == multPol(q, p) # El producto es distributivo respecto de la suma. @given(p=polinomioAleatorio(), q=polinomioAleatorio(), r=polinomioAleatorio()) def test_distributivaProductoSuma(p: Polinomio[int], q: Polinomio[int], r: Polinomio[int]) -> None: assert multPol(p, sumaPol(q, r)) == sumaPol(multPol(p, q), multPol(p, r)) # La comprobación es # > poetry run pytest -v Pol_Producto_polinomios.py # test_conmutativaProducto PASSED # test_distributivaProductoSuma PASSED |
5. Valor de un polinomio en un punto
Usando el tipo abstracto de los polinomios, definir la función
valor :: (Num a, Eq a) => Polinomio a -> a -> a |
tal que valor p c
es el valor del polinomio p
al sustituir su variable por c
. Por ejemplo,
λ> ejPol = consPol 4 3 (consPol 2 (-5) (consPol 0 3 polCero)) λ> ejPol 3*x^4 + -5*x^2 + 3 λ> valor ejPol 0 3 λ> valor ejPol 1 1 λ> valor ejPol (-2) 31 |
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
import TAD.Polinomio (Polinomio, polCero, esPolCero, consPol, grado, coefLider, restoPol) valor :: (Num a, Eq a) => Polinomio a -> a -> a valor p c | esPolCero p = 0 | otherwise = b*c^n + valor r c where n = grado p b = coefLider p r = restoPol p |
from typing import TypeVar from src.TAD.Polinomio import (Polinomio, coefLider, consPol, esPolCero, grado, polCero, restoPol) A = TypeVar('A', int, float, complex) def valor(p: Polinomio[A], c: A) -> A: if esPolCero(p): return 0 n = grado(p) b = coefLider(p) r = restoPol(p) return b*c**n + valor(r, c) |