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
map
0
, 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 foldr
foldr
, pueden redefinirse las funciones
sumaLs
,prodLs
y longLs
.foldr
andLs
está predefinida como la función and
orLs
está predefinida como la función or
append
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 zip
cpares20
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 foldl
op
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.