Diferencia entre revisiones de «Práctica 0 (Paradigmas)»
(Practica 0 - Haskell) |
(Practica 0 - Haskell) |
||
(No se muestran 2 ediciones intermedias del mismo usuario) | |||
Línea 40: | Línea 40: | ||
Definir las siguientes funciones: | Definir las siguientes funciones: | ||
a. valorAbsoluto :: Float → Float, que dado un n ́umero devuelve su valor absoluto. | a. valorAbsoluto :: Float → Float, que dado un n ́umero devuelve su valor absoluto. | ||
b. bisiesto :: Int → Bool, que dado un n ́umero que representa un a ̃no, indica si el mismo es bisiesto. | b. bisiesto :: Int → Bool, que dado un n ́umero que representa un a ̃no, indica si el mismo es bisiesto. | ||
c. factorial :: Int → Int, definida ́unicamente para enteros positivos, que computa el factorial. | |||
c. factorial :: Int → Int, definida ́unicamente para enteros positivos, que computa el factorial. | |||
d. cantDivisoresPrimos :: Int → Int, que dado un entero positivo devuelve la cantidad de divisores primos. | d. cantDivisoresPrimos :: Int → Int, que dado un entero positivo devuelve la cantidad de divisores primos. | ||
Línea 89: | Línea 92: | ||
cantDivisoresPrimos 2 == 1 | cantDivisoresPrimos 2 == 1 | ||
cantDivisoresPrimos 10 == 2 | cantDivisoresPrimos 10 == 2 | ||
== Ejercicio 3 == | |||
Contamos con los tipos Maybe y Either definidos como sigue: | |||
data Maybe a = Nothing | Just a | |||
data Either a b = Left a | Right b | |||
a. Definir la función inverso :: Float → Maybe Float que dado un número devuelve su inverso multiplicativo si está definido, o Nothing en caso | |||
contrario. | |||
b. Definir la función aEntero :: Either Int Bool → Int que convierte a entero una expresi ́on que puede ser | |||
booleana o entera. En el caso de los booleanos, el entero que corresponde es 0 para False y 1 para True. | |||
import Data.Maybe | |||
inverso :: Float -> Maybe Float | |||
inverso x = case x of | |||
0 -> Nothing | |||
x -> Just (1/x) | |||
fromJust (inverso 2) == 0.5 | |||
inverso 0 == Nothing | |||
aEntero :: Either Int Bool -> Int | |||
aEntero x = case x of | |||
Left x -> x | |||
Right True -> 1 | |||
Right False -> 0 | |||
aEntero (Right True) == 1 | |||
aEntero (Right False) == 0 | |||
aEntero (Left 5) == 5 | |||
== Ejercicio 4 == | |||
Definir las siguientes funciones sobre listas: | |||
a. limpiar :: String → String → String, que elimina todas las apariciones de cualquier car ́acter de la primera cadena en la segunda. Por ejemplo, | |||
limpiar ‘‘susto’’ ‘‘puerta’’ eval ́ua a ‘‘pera’’. Nota: String es un renombre de [Char]. La notaci ́on ‘‘hola’’ es equivalente a [‘h’,‘o’,‘l’,‘a’] y a ‘h’:‘o’:‘l’:‘a’:[]. | |||
b. difPromedio :: [Float] → [Float] que dada una lista de n ́umeros devuelve la diferencia de cada uno con el promedio general. Por ejemplo, | |||
difPromedio [2, 3, 4] eval ́ua a [-1, 0, 1]. | |||
c. todosIguales :: [Int] → Bool que indica si una lista de enteros tiene todos sus elementos iguales. | |||
limpiar:: String -> String -> String | |||
limpiar xs = filter (not.(`elem` xs)) | |||
limpiar "susto" "puerta" == "pera" | |||
difPromedio :: [Float] -> [Float] | |||
difPromedio xs = map (subtract promedio) xs | |||
where promedio = sum xs/ fromIntegral (length xs) | |||
difPromedio [2,4,6] == [-2,0,2] | |||
todosIguales :: [Int] -> Bool | |||
todosIguales [] = True | |||
todosIguales (x:ns) = all (== x) ns | |||
--Usando foldr | |||
safeHead :: (Foldable t, Eq a) => t a -> Maybe a | |||
safeHead = foldr (\a _ -> Just a) Nothing | |||
todosIguales2 :: (Foldable t, Eq a) => t a -> Bool | |||
todosIguales2 xs = case safeHead xs of | |||
Nothing -> True | |||
Just a -> all (==a) xs | |||
todosIguales [1,1,1] == True | |||
todosIguales [1,2,1] == False | |||
todosIguales2 [1,1,1] == True | |||
todosIguales2 [1,2,1] == False | |||
== Ejercicio 5 == | |||
Dado el siguiente modelo para ́arboles binarios: | |||
data AB a = Nil | Bin (AB a) a (AB a) | |||
definir las siguientes funciones: | |||
a. vacioAB :: AB a → Bool que indica si un ́arbol es vac ́ıo (i.e. no tiene nodos). | |||
b. negacionAB :: AB Bool → AB Bool que dado un ́arbol de booleanos construye otro formado por la negaci ́on de cada uno de los nodos. | |||
c. productoAB :: AB Int → Int que calcula el producto de todos los nodos del ́arbol. | |||
data AB a = Nil | Bin (AB a) a (AB a) | |||
vacioAB :: AB a -> Bool | |||
instance Eq a => Eq (AB a) where | |||
Nil == Nil = True | |||
(Bin r1 c1 l1) == (Bin r2 c2 l2) = l1==l2 && c1==c2 && r1==r2 | |||
_==_ = False | |||
vacioAB Nil = True | |||
vacioAB _ = False | |||
negacionAB :: AB Bool -> AB Bool | |||
negacionAB Nil = Nil | |||
negacionAB (Bin l c r) = Bin (negacionAB l) (not c) (negacionAB r) | |||
productoAB :: AB Int -> Int | |||
productoAB Nil = 1 | |||
productoAB (Bin l c r) = (productoAB l) * c * productoAB r | |||
productoAB l * c | |||
arbol1 = Bin Nil True Nil | |||
arbol2 = Bin (Bin Nil False Nil) True ( Bin Nil False Nil) | |||
arbol42 = Bin (Bin Nil 7 Nil) 2 ( Bin Nil 3 Nil) | |||
vacioAB Nil == True | |||
vacioAB arbol1 == False | |||
negacionAB Nil == Nil | |||
negacionAB arbol1 == (Bin Nil False Nil) | |||
negacionAB arbol2 == (Bin (Bin Nil True Nil) False ( Bin Nil True Nil))productoAB arbol42 == 42 |
Revisión actual - 04:46 5 sep 2021
Ejercicio 1
Dar el tipo y describir el comportamiento de las siguientes funciones del m ́odulo Prelude de Haskell: null head tail init last take drop (++) concat (!!) elem
"null returns True if a list is empty, otherwise False"
null :: forall (t :: * -> *) a. Foldable t => t a -> Bool "head returns first elemt of list"
head :: forall a. [a] -> a "tail returns list without head"
tail :: forall a. [a] -> [a] "init returns a list withou the last item"
init :: forall a. [a] -> [a] "last returns the last items"
last :: forall a. [a] -> a "take return the first n items" take :: forall a. Int -> [a] -> [a] "drop removes the first n items"
drop :: forall a. Int -> [a] -> [a] "(++) concats lists"
(++) :: forall a. [a] -> [a] -> [a] "concat accepts a list of lists and concatenates them"
concat :: forall (t :: * -> *) a. Foldable t => t [a] -> [a] "(!!) List index (subscript) operator, starting from 0"
(!!) :: forall a. [a] -> Int -> a "returns True if the list contains an item equal to the first argument"
elem :: forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
Ejercicio 2
Definir las siguientes funciones: a. valorAbsoluto :: Float → Float, que dado un n ́umero devuelve su valor absoluto.
b. bisiesto :: Int → Bool, que dado un n ́umero que representa un a ̃no, indica si el mismo es bisiesto.
c. factorial :: Int → Int, definida ́unicamente para enteros positivos, que computa el factorial.
d. cantDivisoresPrimos :: Int → Int, que dado un entero positivo devuelve la cantidad de divisores primos.
valorAbsoluto :: Float -> Float valorAbsoluto x = if x < 0 then x * (-1) else x {- Soluciones Alternativas abs :: Int -> Int abs n | n >= 0 = n | otherwise = -n myabs :: Int -> Int myabs n = if n >= 0 then n else -n -} bisiesto :: Int -> Bool bisiesto x = (mod x 4 == 0) && (mod x 100 /= 0) || (mod x 400 == 0) {- Solucion Alternativa Mas legible isLeapYear :: Year -> Bool isLeapYear y = divisibleBy 400 || (divisibleBy 4 && not (divisibleBy 100)) where divisibleBy x = mod y x == 0 -} factorial :: Int -> Int factorial 0 = 1 factorial x = x * factorial (x-1) {- Solucion Alternativa fac :: (Integral a) => a -> a fac n = product [1..n] -} -- Creditos a https://stackoverflow.com/questions/21276844/prime-factors-in-haskell prime_factors :: Int -> [Int] prime_factors n = case factors of [] -> [n] _ -> factors ++ prime_factors (n `div` (head factors))where factors = take 1 $ filter (\x -> (n `mod` x) == 0) [2 .. n-1] cantDivisoresPrimos :: Int -> Int cantDivisoresPrimos x = length (prime_factors x) -- TESTS valorAbsoluto (-5) == 5 bisiesto 2024 == True bisiesto 1 == False bisiesto 400 == True factorial 2 == 2 factorial 3 == 6 factorial 0 == 1 cantDivisoresPrimos 1 == 1 cantDivisoresPrimos 2 == 1 cantDivisoresPrimos 10 == 2
Ejercicio 3
Contamos con los tipos Maybe y Either definidos como sigue:
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
a. Definir la función inverso :: Float → Maybe Float que dado un número devuelve su inverso multiplicativo si está definido, o Nothing en caso contrario.
b. Definir la función aEntero :: Either Int Bool → Int que convierte a entero una expresi ́on que puede ser booleana o entera. En el caso de los booleanos, el entero que corresponde es 0 para False y 1 para True.
import Data.Maybe inverso :: Float -> Maybe Float inverso x = case x of 0 -> Nothing x -> Just (1/x) fromJust (inverso 2) == 0.5 inverso 0 == Nothing aEntero :: Either Int Bool -> Int aEntero x = case x of Left x -> x Right True -> 1 Right False -> 0 aEntero (Right True) == 1 aEntero (Right False) == 0 aEntero (Left 5) == 5
Ejercicio 4
Definir las siguientes funciones sobre listas:
a. limpiar :: String → String → String, que elimina todas las apariciones de cualquier car ́acter de la primera cadena en la segunda. Por ejemplo, limpiar ‘‘susto’’ ‘‘puerta’’ eval ́ua a ‘‘pera’’. Nota: String es un renombre de [Char]. La notaci ́on ‘‘hola’’ es equivalente a [‘h’,‘o’,‘l’,‘a’] y a ‘h’:‘o’:‘l’:‘a’:[].
b. difPromedio :: [Float] → [Float] que dada una lista de n ́umeros devuelve la diferencia de cada uno con el promedio general. Por ejemplo, difPromedio [2, 3, 4] eval ́ua a [-1, 0, 1].
c. todosIguales :: [Int] → Bool que indica si una lista de enteros tiene todos sus elementos iguales.
limpiar:: String -> String -> String limpiar xs = filter (not.(`elem` xs)) limpiar "susto" "puerta" == "pera" difPromedio :: [Float] -> [Float] difPromedio xs = map (subtract promedio) xs where promedio = sum xs/ fromIntegral (length xs) difPromedio [2,4,6] == [-2,0,2] todosIguales :: [Int] -> Bool todosIguales [] = True todosIguales (x:ns) = all (== x) ns --Usando foldr safeHead :: (Foldable t, Eq a) => t a -> Maybe a safeHead = foldr (\a _ -> Just a) Nothing todosIguales2 :: (Foldable t, Eq a) => t a -> Bool todosIguales2 xs = case safeHead xs of Nothing -> True Just a -> all (==a) xs todosIguales [1,1,1] == True todosIguales [1,2,1] == False todosIguales2 [1,1,1] == True todosIguales2 [1,2,1] == False
Ejercicio 5
Dado el siguiente modelo para ́arboles binarios:
data AB a = Nil | Bin (AB a) a (AB a)
definir las siguientes funciones:
a. vacioAB :: AB a → Bool que indica si un ́arbol es vac ́ıo (i.e. no tiene nodos).
b. negacionAB :: AB Bool → AB Bool que dado un ́arbol de booleanos construye otro formado por la negaci ́on de cada uno de los nodos.
c. productoAB :: AB Int → Int que calcula el producto de todos los nodos del ́arbol.
data AB a = Nil | Bin (AB a) a (AB a) vacioAB :: AB a -> Bool instance Eq a => Eq (AB a) where Nil == Nil = True (Bin r1 c1 l1) == (Bin r2 c2 l2) = l1==l2 && c1==c2 && r1==r2 _==_ = False vacioAB Nil = True vacioAB _ = False negacionAB :: AB Bool -> AB Bool negacionAB Nil = Nil negacionAB (Bin l c r) = Bin (negacionAB l) (not c) (negacionAB r) productoAB :: AB Int -> Int productoAB Nil = 1 productoAB (Bin l c r) = (productoAB l) * c * productoAB r productoAB l * c arbol1 = Bin Nil True Nil arbol2 = Bin (Bin Nil False Nil) True ( Bin Nil False Nil) arbol42 = Bin (Bin Nil 7 Nil) 2 ( Bin Nil 3 Nil) vacioAB Nil == True vacioAB arbol1 == False negacionAB Nil == Nil negacionAB arbol1 == (Bin Nil False Nil) negacionAB arbol2 == (Bin (Bin Nil True Nil) False ( Bin Nil True Nil))productoAB arbol42 == 42