Programacion funcional - Haskell

Colapsar
X
 
  • Tiempo
  • Mostrar
Limpiar Todo
nuevos mensajes
  • Piluex
    Away
    • 10-10-2004
    • 3038

    #1

    Programacion funcional - Haskell

    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

    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)
    Editado por última vez por Piluex; 14-06-2008, 05:43 AM.
  • Galtieri
    Egelito muy activo
    • 19-03-2008
    • 728

    #2
    Te felicito, por ahi es algo simple pero yo todavia no hago nada de nada. En estos dias me pongo a ver si aprendo algo.

    Comentario

    Trabajando...