https://dl.dropbox.com/u/30592764/haskell/practico2.pdf
El 8 está chulo, muchos ejercicios cortitos.
El 8 está chulo, muchos ejercicios cortitos.
Bienvenidos/as al proceloso mar de las Oposiciones. Aquí hay fuentes de información, enlaces a páginas, libros y reflexiones sobre el duro trabajo del opositor/a (a Informática). Además, un podcast de Informática y 7.000 vídeos en Youtube.
> aplica :: (a -> b) -> [a] -> [b]
> aplica f [] = []
> aplica f (x:xs) = f x : aplica f xs
aplica está predefinida como la función
map0, 1 y 0;
y un caso recursivo en el cual se realiza una operación combinando el elemento x con
el resultado de la llamada recursiva. La operación, en el primer caso es \x r -> x + r,
en el segundo caso es \x r -> x * r y en el último caso es \x r -> 1 + r. foldRight que tome como parámetros
el valor e a devolver en el caso básico y la operación op a realizar en el caso recursivo.
> foldRight :: (a -> b -> b) -> b -> [a] -> b
> foldRight op e [] = e
> foldRight op e (x:xs) = x `op` foldRight op e xs
?-foldRight (+) 0 [2,3,4]9
foldRight está predefinida como la función foldrfoldr, pueden redefinirse las funciones
sumaLs,prodLs y longLs.foldrandLs está predefinida como la función andorLs está predefinida como la función orappend está predefinida como el operador (++)vuelta está predefinida como la función reverse> tomaMientras :: (a -> Bool) -> [a] -> [a]
> tomaMientras f = foldr (\x r -> if f x then x:r else []) []
?-tomaMientras (>3) [6,5,2,4,1] [6,5]
tomaMientras está predefinida como la función
takeWhile> filtra :: (a -> Bool) -> [a] -> [a]
> filtra f = foldr (\x r -> if f x then x:r else r) []
?-filtra (>3) [6,5,2,4,1] [6,5,4]
filtra está predefinida como la función
filter> comb :: [a] -> [b] -> [(a,b)]
> comb xs [] = []
> comb [] ys = []
> comb (x:xs) (y:ys) = (x,y):comb xs ys
?-comb [2,3,4] "hola"[(2,'h'),(3,'o'),(4,'l')]
comb está predefinida como la función zipcpares20 calcula los cuadrados de los números pares entre 1 y 20> cpares20 :: [Integer]
> cpares20 = [x ^ 2 | x <- [1..20], x `mod` 2 == 0]
?-cpares20[4,16,36,64,100,144,196,256,324,400]
divisores calcula los divisores de un número> divisores :: Integer -> [Integer]
> divisores n = [d | d <- [1..n], n `mod` d == 0]
?-divisores 24[1,2,3,4,6,8,12,24]
foldr actúa de la siguiente forma: foldr op e [x1,x2,x3] = x1 `op` (x2 `op` (x3 `op` e))
foldr
viene de fold-right, a la derecha.
foldl y realiza la asociación
a la izquierda.
foldl op e [x1,x2,x3] = ((e `op` x1) `op` x2) `op` x3
> foldLeft :: (b -> a -> b) -> b -> [a] -> b
> foldLeft op e [] = e
> foldLeft op e (x:xs) = foldLeft op (e `op` x) xs
?-foldLeft (+) 0 [1,3,4]8
foldLeft está predefinida en Haskell como foldlop es asociativa y e es el elemento neutro de op,
se cunple que:foldr op e = foldl op e
foldr es más eficiente que foldl.
Sin embargo, foldl puede ser útil en cierto tipo de definicionesls2n convierte una lista de dígitos en un número decimal> ls2n :: [Integer] -> Integer
> ls2n = foldl (\r a -> r * 10 + a) 0
?-ls2n [1,3,4]134
foldr1 y foldl1 actúan de
la siguiente forma:foldr1 op [x1,x2,x3] = x1 `op` (x2 `op` x3)
foldl1 op [x1,x2,x3] = (x1 `op` x2) `op` x3
maxLs devuelve el valor máximo de una lista de enteros> maxLs :: [Integer] -> Integer
> maxLs = foldr1 max
?-maxLs [-1,-3,-4]-1
scanr, scanl, scanr1 y scanl1
recorren la lista generando resultados parciales de la siguiente forma: scanr op e [x1,x2,x3] =
[x1 `op` (x2 `op` (x3 `op` e)), x2 `op` (x3 `op` e), x3 `op` e, e]
scanl op e [x1,x2,x3] =
[e, e `op` x1, (e `op` x1) `op` x2, ((e `op` x1) `op` x2) `op` x3]
scanr1 op e [x1,x2,x3] =
[x1 `op` (x2 `op` x3), x2 `op` x3, x3]
scanl1 op e [x1,x2,x3] =
[x1, x1 `op` x2, (x1 `op` x2) `op` x3]
ruffini aplica la regla de ruffini> ruffini :: Float -> [Float] -> [Float]
> ruffini a = scanl1 (\r x -> r * a + x)
?-ruffini 3 [2,4,3][2,10,33]
unfold realiza el proceso inverso a la función foldr> unfold :: (a -> Bool) -> (a -> b) -> (a -> a) -> a -> [b]
> unfold p f g x = if p x then []
> else f x : unfold p f g (g x)
d2b convierte un número decimal en su representación binaria> d2b :: Integer -> [Integer]
> d2b = reverse . unfold (==0) (`mod` 2) (`div` 2)
?-d2b 13[1,1,0,1]
pals convierte devuelve la lista de palabras que forman una cadena de caracteres
> pals :: String -> [String]
> pals = palsAux . quitaEsp
> where palsAux = unfold (=="") tomaPal quitaPal
> tomaPal = takeWhile (not . esp)
> quitaPal = quitaEsp . dropWhile (not . esp)
> quitaEsp = dropWhile esp
> esp x = x == ' ' || x == '\n'
?-pals "mi perro es listo"["mi","perro","es","listo"]
foldA recorre y transforma un árbol en un valor
> foldA :: (a -> b -> b -> b) -> b -> Arbol a -> b
> foldA f e Hoja = e
> foldA f e (Rama x i d) = f x (foldA f e i) (foldA f e d)
sumaArbol calcula la suma de los nodos de un árbol> sumaArbol :: Num n => Arbol n -> n
> sumaArbol = foldA (\x i d -> x + i + d) 0
?-sumaArbol a114
nodosArbol devuelve la lista de nodos de un árbol> nodosArbol :: Arbol a -> [a]
> nodosArbol = foldA (\x i d -> [x] ++ i ++ d) []
?-nodosArbol a1[3,4,5,2]
foldRosal recorre y transforma un rosal en un valor
> foldRosal :: (a -> [b] -> b) -> b -> Rosal a -> b
> foldRosal f e Vacio = e
> foldRosal f e (Nodo x ls) = f x (map (foldRosal f e) ls)
sumaRosal calcula la suma de los nodos de un rosal> sumaRosal :: Num n => Rosal n -> n
> sumaRosal = foldRosal (\x ls -> x + sum ls) 0
nodosRosal devuelve la lista de nodos de un rosal> nodosRosal :: Rosal a -> [a]
> nodosRosal = foldRosal (\x ls -> [x] ++ concat ls) []
fold genérica que recorriese y transformase
todo tipo de estructuras recursivas. Aunque Haskell no permite este tipo de definiciones,
existe una extensión del lenguaje denominada Generic Haskell que permite
definir funciones genéricas, también denominadas politípicas.