Eso, ayer me pico el bichito y hoy en la facu una parte y en la casa de un amigo la terminacion me hice un programita que suma, resta, multiplica y divide polinomios (trabajando con enteros) en haskell.
No creo que haya muchos interesados pero igual lo posteo porque fue divertido aprender haskell y programar esto :P
No creo que haya muchos interesados pero igual lo posteo porque fue divertido aprender haskell y programar esto :P
Código:
module Main where --Codigo de libre distribucion, reutilizacion, copia, venta o lo que se les cante la gana menos sacar mi nombre -- Piluex. --Todo funciona dando por hecho que los terminos de los polinomios estan ordenados de mayor a menor grado --y a las funciones de division y gcd de polinimios se les pasa primero el mayor y luego el menor. --Polinomio, guardamos el grado y el coeficiente de cada termino en una lista. type Poly = [(Int,Int)] --Guardar los polinomios sin coeficientes nulos elimina muchas comparaciones en el resto de las funciones... appNotNull :: (Int,Int) -> Poly -> Poly appNotNull (a,b) xs | b == 0 = xs | b /= 0 = (a,b) : xs --Suma dos polinomios addPoly :: Poly -> Poly -> Poly addPoly [] ys = ys addPoly xs [] = xs addPoly ((a,b):xs) ((c,d):ys) | a == c = (appNotNull (a,b+d) (addPoly xs ys)) | a > c = ( appNotNull (a,b) (addPoly xs ((c,d):ys))) | a < c = ( appNotNull (c,d) (addPoly ((a,b):xs) ys)) --Suma una lista de polinomios addPolys :: [Poly] -> Poly addPolys xs = foldl addPoly [(0,0)] xs --Invierte el signo del coeficiente de un termino invertTerm :: (Int,Int) -> (Int,Int) invertTerm (a,b) = (a,-b) --Resta dos polinomios (suma el primero con el segundo con cambiandole el signo a los coeficientes) subPoly :: Poly -> Poly -> Poly subPoly xs ys = addPoly xs (map invertTerm ys) --Multiplica dos terminos de un polinomio multTermTerm :: (Int,Int) -> (Int,Int) -> (Int,Int) multTermTerm (a,b) (c,d) = (a+c,b*d) --Multiplica un polinomio por un termino multPolyTerm :: Poly -> (Int,Int) -> Poly multPolyTerm ys (a,b) = map (multTermTerm (a,b)) ys --Multiplica dos polinomios multPoly :: Poly -> Poly -> Poly multPoly xs ys = addPolys(map (multPolyTerm ys) xs) --Calcula el cociente del primer termino por el segundo getDivisor :: (Int,Int) -> (Int,Int) -> (Int,Int) getDivisor (a,b) (c,d) = ( a - c , div b d) --Divide dos polinomios devuelve una lista que contiene el cociente y el resto. --TODO: Solo sirve si todas las divisiones dan numeros enteros, y no puse que tire error en el caso contrario -- que habria que detectarlo en "getDivisor", puede caer en loop infinito o tirar cualquier cosa si la division -- no da un cociente de numeros enteros. divPoly :: Poly -> Poly -> Poly -> [Poly] divPoly ((a,b):xs) ((c,d):ys) zs | c > a = [zs,(a,b):xs] | c <= a = divPoly (subPoly ((a,b):xs) (multPoly [(getDivisor (a,b) (c,d))] ((c,d):ys))) ((c,d):ys) ((++) zs [(getDivisor(a,b) (c,d))]) divPoly [] ys zs = [zs,[(0,0)]] --Calcula el maximo comun divisor de una lista de numeros gcds :: [Int] -> Int gcds xs = foldl1 gcd xs --Funcion helper para dividir revdiv :: Int -> (Int,Int) -> (Int,Int) revdiv a (c,d) = (c ,div d a) --Divide todos los coeficientes del polinomio por el mcd de los mismos... reducePoly :: Poly -> Poly reducePoly [] = [(0,0)] reducePoly [(0,0)] = [(0,0)] reducePoly xs = map (revdiv(gcds(snd(unzip(xs))))) xs --Calcula el Maximo Comun Divisor de dos polinomios gcdPoly :: Poly -> Poly -> Poly gcdPoly xs [(0,0)] = xs gcdPoly xs ys = gcdPoly ys (reducePoly (last (divPoly xs ys []))) --Test : main = do let poli1 = [(2,1),(1,7),(0,6)] let poli2 = [(2,1),(1,-5),(0,-6)] print(poli1) print(poli2) print(gcdPoly poli1 poli2)


Comentario