Ej Prog Haskell
Ej Prog Haskell
Ej Prog Haskell
Grupo de Lgica Computacional Dpto. de Ciencias de la Computacin e Inteligencia Articial Universidad de Sevilla Sevilla, 8 de Agosto de 2007 (Versin de 20 de septiembre de 2007)
2 Esta obra est bajo una licencia ReconocimientoNoComercialCompartirIgual 2.5 Spain de Creative Commons.
Se permite: copiar, distribuir y comunicar pblicamente la obra hacer obras derivadas Bajo las condiciones siguientes: Reconocimiento. Debe reconocer los crditos de la obra de la manera especicada por el autor. No comercial. No puede utilizar esta obra para nes comerciales. Compartir bajo la misma licencia. Si altera o transforma esta obra, o genera una obra derivada, slo puede distribuir la obra generada bajo una licencia idntica a sta. Al reutilizar o distribuir la obra, tiene que dejar bien claro los trminos de la licencia de esta obra. Alguna de estas condiciones puede no aplicarse si se obtiene el permiso del titular de los derechos de autor.
Esto es un resumen del texto legal (la licencia completa). Para ver una copia de esta licencia, visite http://creativecommons.org/licenses/by-nc-sa/2.5/es/ o envie una carta a Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
ndice general
1. Introduccin a la programacin funcional 1.1. Factorial . . . . . . . . . . . . . . . . . . 1.2. Nmero de combinaciones . . . . . . . . 1.3. Comprobacin de nmero impar . . . . 1.4. Cuadrado . . . . . . . . . . . . . . . . . 1.5. Suma de cuadrados . . . . . . . . . . . . 1.6. Raices de ecuaciones de segundo grado 1.7. Valor absoluto . . . . . . . . . . . . . . . 1.8. Signo . . . . . . . . . . . . . . . . . . . . 1.9. Conjuncin . . . . . . . . . . . . . . . . . 1.10. Anterior de un nmero natural . . . . . 1.11. Potencia . . . . . . . . . . . . . . . . . . 1.12. Funcin identidad . . . . . . . . . . . . . 7 7 9 10 11 12 13 13 14 15 15 16 17 19 20 20 21 22 23 23 24 25 26 27 27 28 29 30 30 31
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
2. Nmeros y funciones 2.1. Casi igual . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Siguiente de un nmero . . . . . . . . . . . . . . . . . . 2.3. Doble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4. Mitad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5. Inverso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6. Potencia de dos . . . . . . . . . . . . . . . . . . . . . . . 2.7. Reconocimiento de nmeros positivos . . . . . . . . . . 2.8. Aplicacin de una funcin a los elementos de una lista 2.9. Filtrado mediante una propiedad . . . . . . . . . . . . . 2.10. Suma de los elementos de una lista . . . . . . . . . . . . 2.11. Producto de los elementos de una lista . . . . . . . . . . 2.12. Conjuncin sobre una lista . . . . . . . . . . . . . . . . . 2.13. Disyuncin sobre una lista . . . . . . . . . . . . . . . . . 2.14. Plegado por la derecha . . . . . . . . . . . . . . . . . . . 2.15. Plegado por la izquierda . . . . . . . . . . . . . . . . . . 2.16. Resultados acumulados . . . . . . . . . . . . . . . . . . 3
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
4 2.17. 2.18. 2.19. 2.20. 2.21. 2.22. 2.23. 2.24. 2.25. 2.26. 2.27. 2.28. Lista de factoriales . . . . . . . . . . Iteracin hastaque . . . . . . . . . . Composicin de funciones . . . . . . Intercambio de orden de argumentos Relacin de divisibilidad . . . . . . . Lista de divisores de un nmero . . Comprobacin de nmero primo . . Lista de primos . . . . . . . . . . . . Clculo del da de la semana . . . . . Diferenciacin numrica . . . . . . . Clculo de la raz cuadrada . . . . . Clculo de ceros de una funcin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ndice general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 33 33 34 34 35 35 36 36 37 38 39 41 43 43 44 45 45 45 47 48 48 49 50 50 51 52 53 54 56 57 58 59 61 62 64 64 65 65 66
3. Estructuras de datos 3.1. Relacin de igualdad entre listas . . . . . . . . . . . . . . . . 3.2. Concatenacin de listas . . . . . . . . . . . . . . . . . . . . . . 3.3. Concatenacin de una lista de listas . . . . . . . . . . . . . . 3.4. Cabeza de una lista . . . . . . . . . . . . . . . . . . . . . . . . 3.5. Resto de una lista . . . . . . . . . . . . . . . . . . . . . . . . . 3.6. ltimo elemento . . . . . . . . . . . . . . . . . . . . . . . . . . 3.7. Lista sin el ltimo elemento . . . . . . . . . . . . . . . . . . . 3.8. Segmento inicial . . . . . . . . . . . . . . . . . . . . . . . . . . 3.9. Segmento inicial ltrado . . . . . . . . . . . . . . . . . . . . . 3.10. Segmento nal . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.11. Segmento nal ltrado . . . . . . . . . . . . . . . . . . . . . . 3.12. Nsimo elemento de una lista . . . . . . . . . . . . . . . . . 3.13. Inversa de una lista . . . . . . . . . . . . . . . . . . . . . . . . 3.14. Longitud de una lista . . . . . . . . . . . . . . . . . . . . . . . 3.15. Comprobacin de pertenencia de un elemento a una lista . . 3.16. Comprobacin de no pertenencia de un elemento a una lista 3.17. Comprobacin de que una lista est ordenada . . . . . . . . 3.18. Comprobacin de la igualdad de conjuntos . . . . . . . . . . 3.19. Insercin ordenada de un elemento en una lista . . . . . . . . 3.20. Ordenacin por insercin . . . . . . . . . . . . . . . . . . . . 3.21. Mnimo elemento de una lista . . . . . . . . . . . . . . . . . . 3.22. Mezcla de dos listas ordenadas . . . . . . . . . . . . . . . . . 3.23. Ordenacin por mezcla . . . . . . . . . . . . . . . . . . . . . . 3.24. Dgito correspondiente a un carcter numrico . . . . . . . . 3.25. Carcter correspondiente a un dgito . . . . . . . . . . . . . . 3.26. Lista innita de nmeros . . . . . . . . . . . . . . . . . . . . . 3.27. Lista con un elemento repetido . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
ndice general 3.28. 3.29. 3.30. 3.31. 3.32. 3.33. 3.34. 3.35. 3.36. 3.37. 3.38. 3.39. 3.40. 3.41. 3.42. 3.43. 3.44. 3.45. 3.46. 3.47. 3.48. 3.49. 3.50. 3.51. 3.52. 3.53. 3.54. Lista con un elemento repetido un nmero dado de veces Iteracin de una funcin . . . . . . . . . . . . . . . . . . . Conversin de nmero entero a cadena . . . . . . . . . . Clculo de primos mediante la criba de Erasttenes . . . Comprobacin de que todos los elementos son pares . . . Comprobacin de que todos los elementos son impares . Tringulos numricos . . . . . . . . . . . . . . . . . . . . . Posicin de un elemento en una lista . . . . . . . . . . . . Ordenacin rpida . . . . . . . . . . . . . . . . . . . . . . Primera componente de un par . . . . . . . . . . . . . . . Segunda componente de un par . . . . . . . . . . . . . . . Componentes de una terna . . . . . . . . . . . . . . . . . Creacin de variables a partir de pares . . . . . . . . . . . Divisin de una lista . . . . . . . . . . . . . . . . . . . . . Sucesin de Fibonacci . . . . . . . . . . . . . . . . . . . . . Incremento con el mnimo . . . . . . . . . . . . . . . . . . Longitud de camino entre puntos bidimensionales . . . . Nmeros racionales . . . . . . . . . . . . . . . . . . . . . . Mximo comn divisor . . . . . . . . . . . . . . . . . . . . Bsqueda en una lista de asociacin . . . . . . . . . . . . Emparejamiento de dos listas . . . . . . . . . . . . . . . . Emparejamiento funcional de dos listas . . . . . . . . . . Curricacin . . . . . . . . . . . . . . . . . . . . . . . . . . Funciones sobre rboles . . . . . . . . . . . . . . . . . . . Bsqueda en lista ordenada . . . . . . . . . . . . . . . . . Movimiento segn las direcciones . . . . . . . . . . . . . Los racionales como tipo abstracto de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4. Aplicaciones de programacin funcional 4.1. Segmentos iniciales . . . . . . . . . . . . . . 4.2. Segmentos nales . . . . . . . . . . . . . . . 4.3. Segmentos . . . . . . . . . . . . . . . . . . . 4.4. Sublistas . . . . . . . . . . . . . . . . . . . . 4.5. Comprobacin de subconjunto . . . . . . . 4.6. Comprobacin de la igualdad de conjuntos 4.7. Permutaciones . . . . . . . . . . . . . . . . . 4.8. Combinaciones . . . . . . . . . . . . . . . . 4.9. El problema de las reinas . . . . . . . . . . . 4.10. Nmeros de Hamming . . . . . . . . . . . . Bibliografa
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
6 Indice de deniciones
1.3. Comprobacin de nmero impar . . . . . . . . . . . . . . . . . . . . . . . 10 1.4. Cuadrado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5. Suma de cuadrados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.6. Raices de ecuaciones de segundo grado . . . . . . . . . . . . . . . . . . . 13 1.7. Valor absoluto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.8. Signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.9. Conjuncin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.10. Anterior de un nmero natural . . . . . . . . . . . . . . . . . . . . . . . . 15 1.11. Potencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.12. Funcin identidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.1.
Factorial
Ejercicio 1.1. Denir la funcin factorial tal que factorial n es el factorial de n. Por ejemplo,
factorial 4 ;24
Solucin: Vamos a presentar distintas deniciones. 7
fact2 fact2 | |
fact4 fact4 | |
prop_equivalencia :: Integer -> Property prop_equivalencia x = x >= 0 ==> (fact2 x == fact1 x && fact3 x == fact1 x && fact4 x == fact1 x && fact5 x == fact1 x && fact6 x == fact1 x && fact7 x == fact1 x)
Comprobacin
factorial = fact5
1.2.
Nmero de combinaciones
Ejercicio 1.2. Denir la funcin comb tal que comb n k es el nmero de combinaciones de n elementos tomados de k en k; es decir, n m Por ejemplo.
n! k! (n k)!
comb 6 2 ; 15
Solucin:
10
1.3.
Ejercicio 1.3. Denir la funcin impar tal que impar x se verica si el nmero x es impar. Por ejemplo,
impar 7 impar 6
; ;
True False
impar4 :: Integer -> Bool impar4 x | x > 0 = impar4_aux | otherwise = impar4_aux where impar4_aux 0 = impar4_aux 1 = impar4_aux (n+2) =
Las deniciones son equivalentes:
prop_equivalencia :: Integer -> Bool prop_equivalencia x = impar2 x == impar1 x && impar3 x == impar1 x && impar4 x == impar1 x
Comprobacin
1.4. Cuadrado
11
1.4.
Cuadrado
Ejercicio 1.4. Denir la funcin cuadrado tal que cuadrado x es el cuadrado del nmero x. Por ejemplo,
cuadrado 3 ;
cuadrado = cuadrado_1
Las deniciones son equivalentes:
prop_equivalencia :: Int -> Bool prop_equivalencia x = cuadrado_2 x == cuadrado_1 x && cuadrado_3 x == cuadrado_1 x
Comprobacin
12
1.5.
Suma de cuadrados
Ejercicio 1.5. Denir la funcin suma_de_cuadrados tal que suma_de_cuadrados l es la suma de los cuadrados de los elementos de la lista l. Por ejemplo,
suma_de_cuadrados [1,2,3] ;
14
suma_de_cuadrados_3 :: [Integer] -> Integer suma_de_cuadrados_3 l = sum (map (\x -> x*x) l)
4. Por recursin:
prop_equivalencia :: [Integer] -> Bool prop_equivalencia xs = suma_de_cuadrados_2 xs == suma_de_cuadrados_1 xs && suma_de_cuadrados_3 xs == suma_de_cuadrados_1 xs && suma_de_cuadrados_4 xs == suma_de_cuadrados_1 xs
Comprobacin
13
1.6.
Ejercicio 1.6. Denir la funcin raices tal que raices a b c es la lista de las raices de la ecuacin ax2 + bc + c = 0. Por ejemplo,
raices 1 3 2
[-1.0,-2.0]
raices_1 :: Double -> Double -> Double -> [Double] raices_1 a b c = [ (-b+sqrt(b*b-4*a*c))/(2*a), (-b-sqrt(b*b-4*a*c))/(2*a) ]
2. Con entornos locales
raices_2 :: Double -> Double -> Double -> [Double] raices_2 a b c = [(-b+d)/n, (-b-d)/n] where d = sqrt(b*b-4*a*c) n = 2*a
La segunda es mejor en legibilidad y en eciencia:
Main> :set +s Main> raices_1 1 [-1.0,-2.0] (134 reductions, Main> raices_2 1 [-1.0,-2.0] (104 reductions,
1.7.
Valor absoluto
Ejercicio 1.7. Redenir la funcin abs tal que abs x es el valor absoluto de x. Por ejemplo,
14
n_abs_1 :: (Num a, Ord a) => a -> a n_abs_1 x = if x>0 then x else (-x)
2. Con guardas:
prop_equivalencia :: Int -> Bool prop_equivalencia x = n_abs_1 x == abs x && n_abs_2 x == abs x
1.8.
Signo
Ejercicio 1.8. Redenir la funcin signum tal que signum x es -1 si x es negativo, 0 si x es cero y 1 si x es positivo. Por ejemplo,
1.9. Conjuncin
15
1.9.
Conjuncin
Ejercicio 1.9. Redenir la funcin && tal que x && y es la conjuncin de x e y Por ejemplo,
(&&&) :: Bool -> Bool -> Bool False &&& x = False True &&& x = x
Las deniciones son equivalentes:
1.10.
Ejercicio 1.10. Denir la funcin anterior tal que anterior x es el anterior del nmero natural x. Por ejemplo,
16
1.11.
Potencia
Ejercicio 1.11. Redenir la funcin potencia tal que potencia x y es x y . Por ejemplo,
potencia_1 :: Num a => a -> Int -> a potencia_1 x 0 = 1 potencia_1 x (n+1) = x * (potencia_1 x n)
2. Por condicionales:
potencia_2 :: Num a => a -> Int -> a potencia_2 x n = if n==0 then 1 else x * potencia_2 x (n-1)
3. Denicin eciente:
potencia_3 :: Num a => a -> Int -> a potencia_3 x 0 = 1 potencia_3 x n | n > 0 = f x (n-1) x where f _ 0 y = y f x n y = g x n where g x n | even n = g (x*x) (n`quot`2) | otherwise = f x (n-1) (x*y)
Las deniciones son equivalentes:
17
:: Int -> Int -> Property x n = n == x^n && n == x^n && n == x^n)
1.12.
Funcin identidad
id 3 ; 3
Solucin: La denicin es
18
19
20
2.1.
Casi igual
Ejercicio 2.1. Denir el operador ~= tal que x ~= y se verica si | x y| < 0,0001. Por ejemplo,
infix 4 ~= (~=) :: Float -> Float -> Bool x ~= y = abs(x-y) < 0.0001
2.2.
Siguiente de un nmero
Ejercicio 2.2. Denir la funcin siguiente tal que siguiente x sea el siguiente del nmero entero x. Por ejemplo,
siguiente 3 ; 4
Solucin: Presentamos distintas deniciones: 1. Mediante seccin:
2.3. Doble
21
siguiente = siguiente_1
Las deniciones son equivalentes:
2.3.
Doble
Ejercicio 2.3. Denir la funcin doble tal que doble x es el doble de x. Por ejemplo,
doble 3 ; 6
Solucin: Se presentan distintas deniciones: 1. Denicin ecuacional:
prop_equivalencia :: Int -> Bool prop_equivalencia x = doble_2 x == doble_1 x && doble_3 x == doble_1 x
22 Comprobacin
2.4.
Mitad
Ejercicio 2.4. Denir la funcin mitad tal que mitad x es la mitad de x. Por ejemplo,
prop_equivalencia :: Double -> Bool prop_equivalencia x = mitad_2 x == mitad_1 x && mitad_3 x == mitad_1 x
Comprobacin
2.5. Inverso
23
2.5.
Inverso
Ejercicio 2.5. Denir la funcin inverso tal que inverso x es el inverso de x. Por ejemplo,
inverso 2 ; 0.5
Solucin: Se presentan distintas deniciones: 1. Denicin ecuacional:
prop_equivalencia :: Double -> Property prop_equivalencia x = x /= 0 ==> (inverso_2 x == inverso_1 x && inverso_3 x == inverso_1 x)
Comprobacin
2.6.
Potencia de dos
Ejercicio 2.6. Denir la funcin dosElevadoA tal que dosElevadoA x es 2x . Por ejemplo,
dosElevadoA 3 ; 8
Solucin: Se presentan distintas deniciones:
24 1. Denicin ecuacional:
prop_equivalencia :: Int -> Property prop_equivalencia x = x >= 0 ==> (dosElevadoA_2 x == dosElevadoA_1 x && dosElevadoA_3 x == dosElevadoA_1 x)
Comprobacin
2.7.
Ejercicio 2.7. Denir la funcin esPositivo tal que esPositivo se verica si x es positivo. Por ejemplo,
2.8. Aplicacin de una funcin a los elementos de una lista 2. Denicin con instanciacin parcial:
25
prop_equivalencia :: Int -> Bool prop_equivalencia x = esPositivo_2 x == esPositivo_1 x && esPositivo_3 x == esPositivo_1 x
Comprobacin
2.8.
Ejercicio 2.8. Redenir la funcin map tal que map f l es la lista obtenida aplicando f a cada elemento de l. Por ejemplo,
n_map_1 :: (a -> b) -> [a] -> [b] n_map_1 f [] = [] n_map_1 f (x:xs) = f x : n_map_1 f xs
2. Con listas intensionales:
prop_equivalencia :: [Int] -> Bool prop_equivalencia xs = n_map_1 (*2) xs == map (*2) xs && n_map_2 (*2) xs == map (*2) xs
Comprobacin
2.9.
Ejercicio 2.9. Redenir la funcin filter tal que filter p l es la lista de los elementos de l que cumplen la propiedad p. Por ejemplo,
n_filter_1 :: (a -> Bool) -> [a] -> [a] n_filter_1 p [] = [] n_filter_1 p (x:xs) | p x = x : n_filter_1 p xs | otherwise = n_filter_1 p xs
2. Denicin con listas intensionales:
n_filter_2 :: (a -> Bool) -> [a] -> [a] n_filter_2 p xs = [ x | x <- xs, p x ]
Las deniciones son equivalentes cuando la propiedad es even:
prop_equivalencia :: [Int] -> Bool prop_equivalencia xs = n_filter_1 even xs == filter even xs && n_filter_2 even xs == filter even xs
Comprobacin
27
2.10.
Ejercicio 2.10. Redenir la funcin sum tal que sum l es la suma de los elementos de l. Por ejemplo,
n_sum [1,3,6] ; 10
Solucin: Presentamos distintas deniciones: 1. Denicin recursiva:
2.11.
Ejercicio 2.11. Redenir la funcin product tal que product l es el producto de los elementos de l. Por ejemplo,
product [2,3,5] ; 30
Solucin: Presentamos distintas deniciones: 1. Denicin recursiva
28
prop_equivalencia :: [Int] -> Bool prop_equivalencia xs = n_product_1 xs == product xs && n_product_2 xs == product xs
Comprobacin
2.12.
Ejercicio 2.12. Redenir la funcin and tal que and l se verica si todos los elementos de l son verdaderos. Por ejemplo,
n_and_1 :: [Bool] -> Bool n_and_1 [] = True n_and_1 (x:xs) = x && n_and_1 xs
2. Denicin con plegado:
29
2.13.
Ejercicio 2.13. Redenir la funcin or tal que or l se verica si algn elemento de l es verdadero. Por ejemplo,
prop_equivalencia :: [Bool] -> Bool prop_equivalencia xs = n_or_1 xs == or xs && n_or_2 xs == or xs Main> quickCheck prop_equivalencia OK, passed 100 tests.
30
2.14.
Ejercicio 2.14. Redenir la funcin foldr tal que foldr op e l pliega por la derecha la lista l colocando el operador op entre sus elementos y el elemento e al nal. Es decir,
foldr op e [x1,x2,x3] ; x1 op (x2 op (x3 op e)) foldr op e [x1,x2,...,xn] ; x1 op (x2 op (... op (xn op e)))
Por ejemplo,
n_foldr :: (a -> b -> b) -> b -> [a] -> b n_foldr f e [] = e n_foldr f e (x:xs) = f x (n_foldr f e xs)
2.15.
Ejercicio 2.15. Redenir la funcin foldl tal que foldl op e l pliega por la izquierda la lista l colocando el operador op entre sus elementos y el elemento e al principio. Es decir,
foldl op e [x1,x2,x3] ; (((e op x1) op x2) op x3 foldl op e [x1,x2,...,xn] ; (...((e op x1) op x2) ... op xn
Por ejemplo,
n_foldl :: (a -> b -> a) -> a -> [b] -> a n_foldl f z [] = z n_foldl f z (x:xs) = n_foldl f (f z x) xs
Las deniciones son equivalentes:
prop_equivalencia :: Int -> [Int] -> Bool prop_equivalencia n xs = n_foldl (+) n xs == foldl (+) n xs
Comprobacin
31
2.16.
Resultados acumulados
Ejercicio 2.16. Redenir la funcin scanr tal que scanr op e l pliega por la derecha la lista l colocando el operador op entre sus elementos y el elemento e al nal y escribe los resultados acumulados. Es decir,
n_scanr :: (a -> b -> b) -> b -> [a] -> [b] n_scanr f q0 [] = [q0] n_scanr f q0 (x:xs) = f x q : qs where qs@(q:_) = n_scanr f q0 xs
Las deniciones son equivalentes:
prop_equivalencia :: Int -> [Int] -> Bool prop_equivalencia n xs = n_scanr (+) n xs == scanr (+) n xs
Comprobacin
2.17.
Lista de factoriales
Ejercicio 2.17. Denir la funcin factoriales tal que factoriales n es la lista de los factoriales desde el factorial de 0 hasta el factorial de n. Por ejemplo,
factoriales 5 ; [1,1,2,6,24,120]
Solucin: Se presentan distintas deniciones: 1. Denicin recursiva
32
factoriales_1 :: Integer -> [Integer] factoriales_1 n = reverse (aux n) where aux 0 = [1] aux (n+1) = (factorial (n+1)) : aux n
2. Denicin recursiva con acumuladores:
factoriales_2 :: Integer -> [Integer] factoriales_2 n = reverse (aux (n+1) 0 [1]) where aux n m (x:xs) = if n==m then xs else aux n (m+1) (((m+1)*x):x:xs)
3. Denicin con listas intensionales:
prop_equivalencia :: Integer -> Property prop_equivalencia n = n >= 0 ==> (factoriales_5 n == factoriales_1 n && factoriales_2 n == factoriales_1 n && factoriales_3 n == factoriales_1 n && factoriales_4 n == factoriales_1 n && factoriales_5 n == factoriales_1 n)
Comprobacin
33
Main> :set +s Main> factoriales_1 100 [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,...] (171696 reductions, 322659 cells) Main> factoriales_2 100 [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,...] (2457 reductions, 13581 cells) Main> factoriales_3 100 [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,...] (169929 reductions, 319609 cells) Main> factoriales_4 100 [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,...] (169930 reductions, 319611 cells) Main> factoriales_5 100 [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,...] (2559 reductions, 12876 cells) Main>
Se observa que las ms ecientes son la 2 y la 5.
2.18.
Iteracin hastaque
Ejercicio 2.18. Redenir la funcin until tal que until p f x aplica la f a x el menor nmero posible de veces, hasta alcanzar un valor que satisface el predicado p. Por ejemplo,
n_until :: (a -> Bool) -> (a -> a) -> a -> a n_until p f x = if p x then x else n_until p f (f x)
2.19.
Composicin de funciones
Ejercicio 2.19. Redenir la funcin (.) tal que f . g es la composicin de las funciones f y g; es decir, la funcin que aplica x en f(g(x)). Por ejemplo,
34
2.20.
Ejercicio 2.20. Redenir la funcin flip que intercambia el orden de sus argumentos. Por ejemplo,
2.21.
Relacin de divisibilidad
Ejercicio 2.21. Denir la funcin divisible tal que divisible x y se verica si x es divisible por y. Por ejemplo,
35
2.22.
Ejercicio 2.22. Denir la funcin divisores tal que divisores x es la lista de los divisores de x. Por ejemplo,
divisores 12 ; [1,2,3,4,6,12]
Solucin: Se presentan distintas deniciones: 1. Mediante ltro:
divisores = divisores_2
2.23.
Ejercicio 2.23. Denir la funcin primo tal que primo x se verica si x es primo. Por ejemplo,
36
2.24.
Lista de primos
Ejercicio 2.24. Denir la funcin primos tal que primos x es la lista de los nmeros primos menores o iguales que x. Por ejemplo,
primos 40 ; [2,3,5,7,11,13,17,19,23,29,31,37]
Solucin: Se presentan distintas deniciones: 1. Mediante ltrado:
2.25.
Ejercicio 2.25. Denir la funcin da tal que dia d m a es el da de la semana correspondiente al da d del mes m del ao a. Por ejemplo,
da 31 12 2007 ; "lunes"
Solucin:
nmeroDa d m a es el nmero de das trancurridos desde el 1 de enero del ao 0 hasta el da d del mes m del ao a. Por ejemplo, nmeroDeDas 31 12 2007 ; 733041 nmeroDeDas d m a = (a-1)*365 + nmeroDeBisiestos a + sum (take (m-1) (meses a)) + d
37
nmeroDeBisiestos a = length (filter bisiesto [1..a-1]) bisiesto a se verica si el ao a es bisiesto. La denicin de ao bisiesto es
un ao divisible por 4 es un ao bisiesto (por ejemplo 1972); excepcin: si es divisible por 100, entonces no es un ao bisiesto excepcin de la excepcin: si es divisible por 400, entonces es un ao bisiesto (por ejemplo 2000).
bisiesto a = divisible a 4 && (not(divisible a 100) || divisible a 400) meses a es la lista con el nmero de das del los meses del ao a. Por ejemplo, meses 2000 ; [31,29,31,30,31,30,31,31,30,31,30,31] meses a = [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] where feb | bisiesto a = 29 | otherwise = 28 daSemana n es el nsimo da de la semana comenzando con 0 el domingo. Por ejemplo, daSemana 2 ; "martes" daSemana daSemana daSemana daSemana daSemana daSemana daSemana 0 1 2 3 4 5 6 = = = = = = = "domingo" "lunes" "martes" "mircoles" "jueves" "viernes" "sbado"
2.26.
Diferenciacin numrica
Ejercicio 2.26. Denir la funcin derivada tal que derivada a f x es el valor de la derivada de la funcin f en el punto x con aproximacin a. Por ejemplo,
38
derivada :: Float -> (Float -> Float) -> Float -> Float derivada a f x = (f(x+a)-f(x))/a
Ejercicio 2.27. Denir las siguientes versiones de derivada:
derivadaBurda cuando la aproximacin es 0.01. derivadaFina cuando la aproximacin es 0.0001. derivadaSuper cuando la aproximacin es 0.000001.
Por ejemplo,
derivadaFinaDelSeno pi ; -0.9989738
Solucin:
2.27.
Ejercicio 2.29. Denir la funcin RaizCuadrada tal que raiz x es la raz cuadrada de x calculada usando la siguiente propiedad x Si y es una aproximacin de x, entonces 1 2 ( y + y ) es una aproximacin mejor. Por ejemplo,
39
raizCuadrada 9 ; 3.00000000139698
Solucin:
raizCuadrada :: Double -> Double raizCuadrada x = until aceptable mejorar 1 where mejorar y = 0.5*(y+x/y) aceptable y = abs(y*y-x) < 0.00001
2.28.
Ejercicio 2.30. Denir la funcin puntoCero tal que puntoCero f es un cero de la funcin f calculado usando la siguiente propiedad Si b es una aproximacin para el punto cero de f , entonces b aproximacin. Por ejemplo,
f (b) f (b)
es una mejor
puntoCero f = until aceptable mejorar 1 where mejorar b = b - f b / derivadaFina f b aceptable b = abs (f b) < 0.00001
Ejercicio 2.31. Usando puntoCero, denir las siguientes funciones:
raz_cuadrada tal que raz_cuadrada x es la raz cuadrada de x. raz_cbica tal que raz_cbica x es la raz cbica de x. arco_seno tal que arco_seno x es el arco cuyo seno es x. arco_coseno tal que arco_coseno x es el arco cuyo coseno es x.
Solucin:
40
= = = =
41
42
43
3.1.
Ejercicio 3.1. Denir la funcin igualLista tal que igualLista xs ys se verica si las dos listas xs e ys son iguales. Por ejemplo,
igualLista :: Eq a => [a] -> [a] -> Bool igualLista [1,2,3,4,5] [1..5] ; True igualLista [1,3,2,4,5] [1..5] ; False
Nota: igualLista es equivalente a ==. Solucin:
:: Eq a => [a] -> [a] -> Bool [] [] = True (x:xs) (y:ys) = x==y && igualLista xs ys _ _ = False
3.2.
Concatenacin de listas
Ejercicio 3.2. Denir la funcin conc tal que conc l1 l2 es la concatenacin de l1 y l2. Por ejemplo,
conc :: [a] -> [a] -> [a] conc [] ys = ys conc (x:xs) ys = x : (conc xs ys)
3.3.
Ejercicio 3.3. Redenir la funcin concat tal que concat l es la concatenacin de las lista de l. Por ejemplo,
concat_3 :: [[a]] -> [a] concat_3 xss = [x | xs <- xss, x <- xs]
Las deniciones son equivalentes:
45
3.4.
Ejercicio 3.4. Redenir la funcin head tal que head l es la cabeza de la lista l. Por ejemplo,
3.5.
Ejercicio 3.5. Redenir la funcin tail tal que tail l es el resto de la lista l. Por ejemplo,
tail [3,5,2] ; [5,2] tail (tail [1]) ; Program error: pattern match failure: tail []
Solucin:
3.6.
ltimo elemento
Ejercicio 3.6. Redenir la funcin last tal que last l es el ltimo elemento de la lista l. Por ejemplo,
46
prop_equivalencia :: [Int] -> Property prop_equivalencia xs = not (null xs) ==> (n_last_1 xs == last xs && n_last_2 xs == last xs && n_last_3 xs == last xs && n_last_4 xs == last xs && n_last_5 xs == last xs)
Comprobacin
47
3.7.
Ejercicio 3.7. Redenir la funcin init tal que init l es la lista l sin el ltimo elemento. Por ejemplo,
prop_equivalencia :: [Int] -> Property prop_equivalencia xs = not (null xs) ==> (n_init_1 xs == init xs && n_init_2 xs == init xs && n_init_3 xs == init xs)
Comprobacin
48
3.8.
Segmento inicial
Ejercicio 3.8. Denir la funcin take tal que take n l es la lista de los n primeros elementos de l. Por ejemplo,
-> = = =
3.9.
Ejercicio 3.9. Redenir la funcin takeWhile tal que takeWhile p l es la lista de los elementos iniciales de l que verican el predicado p. Por ejemplo,
n_takeWhile :: (a -> Bool) -> [a] -> [a] n_takeWhile p [] = [] n_takeWhile p (x:xs) | p x = x : n_takeWhile p xs | otherwise = []
Las deniciones son equivalentes:
49
3.10.
Segmento nal
Ejercicio 3.10. Redenir la funcin drop tal que drop n l es la lista obtenida eliminando los primeros n elementos de la lista l. Por ejemplo,
50
3.11.
Ejercicio 3.11. Redenir la funcin dropWhile tal que dropWhile p l es la lista l sin los elementos iniciales que verican el predicado p. Por ejemplo,
n_dropWhile :: (a -> Bool) -> [a] -> [a] n_dropWhile p [] = [] n_dropWhile p l@(x:xs) | p x = n_dropWhile p xs | otherwise = l
Las deniciones son equivalentes:
3.12.
Ejercicio 3.12. Denir la funcin nth tal que nth l n es elemento nsimo de l, empezando a numerar con el 0. Por ejemplo,
nth [1,3,2,4,9,7] 3 ; 4
Nota: nth es equivalente a (!!). Solucin:
nth :: [a] -> Int -> a nth (x:_) 0 = x nth (_:xs) n = nth xs (n-1)
Las deniciones son equivalentes:
51
prop_equivalencia :: [Int] -> Int -> Property prop_equivalencia xs n = 0 < n && n < length xs ==> nth xs n == xs!!n
Comprobacin
3.13.
Ejercicio 3.13. Redenir la funcin reverse tal que reverse l es la inversa de l. Por ejemplo,
n_reverse_2 :: [a] -> [a] n_reverse_2 xs = n_reverse_2_aux xs [] where n_reverse_2_aux [] ys = ys n_reverse_2_aux (x:xs) ys = n_reverse_2_aux xs (x:ys)
3. Con plegado:
prop_equivalencia :: [Int] -> prop_equivalencia xs = n_reverse_1 xs == reverse n_reverse_2 xs == reverse n_reverse_3 xs == reverse
52 Comprobacin
3.14.
Ejercicio 3.14. Redenir la funcin length tal que length l es el nmero de elementos de l. Por ejemplo,
length [1,3,6] ; 3
Solucin: Se presentan distintas deniciones: 1. Denicin recursiva:
3.15. Comprobacin de pertenencia de un elemento a una lista Las deniciones son equivalentes:
53
:: xs == == == ==
[Int] -> Bool = length xs && length xs && length xs && length xs
3.15.
Ejercicio 3.15. Redenir la funcin elem tal que elem e l se verica si e es un elemento de l. Por ejemplo,
n_elem_1 :: Eq a => a -> [a] -> Bool n_elem_1 _ [] = False n_elem_1 x (y:ys) = (x==y) || n_elem_1 x ys
2. Denicin con plegado:
n_elem_2 :: Eq a => a -> [a] -> Bool n_elem_2 x = foldl (\z y -> z || x==y) False
3. Denicin con or y map
n_elem_3 :: Eq a => a -> [a] -> Bool n_elem_3 x ys = or (map (==x) ys)
4. Denicin con or, map y (.)
54
n_elem_5 :: Eq a => a -> [a] -> Bool n_elem_5 x ys = or [x==y | y <- ys]
6. Denicin con any y (.)
3.16.
Ejercicio 3.16. Redenir la funcin notElem tal que notElem e l se verica si e no es un elemento de l. Por ejemplo,
55
n_notElem_1 :: Eq a => a -> [a] -> Bool n_notElem_1 _ [] = True n_notElem_1 x (y:ys) = (x/=y) && n_notElem_1 x ys
2. Denicin con plegado:
n_notElem_2 :: Eq a => a -> [a] -> Bool n_notElem_2 x = foldl (\z y -> z && x/=y) True
3. Denicin con or y map
n_notElem_3 :: Eq a => a -> [a] -> Bool n_notElem_3 x ys = and (map (/=x) ys)
4. Denicin con or, map y (.)
n_notElem_4 :: Eq a => a -> [a] -> Bool n_notElem_4 x = and . map (/=x)
5. Denicin con or y lista intensional:
n_notElem_5 :: Eq a => a -> [a] -> Bool n_notElem_5 x ys = and [x/=y | y <- ys]
6. Denicin con any y (.)
56
:: Int -> [Int] x ys = ys == notElem x ys == notElem x ys == notElem x ys == notElem x ys == notElem x ys == notElem x ys == notElem x
3.17.
Ejercicio 3.17. Denir la funcin lista_ordenada tal que lista_ordenada l se verica si la lista l est ordenada de menor a mayor. Por ejemplo,
=> [a] -> Bool = True = True = (x <= y) && lista_ordenada_1 (y:xs)
:: Ord a => [a] -> Bool [] = True [_] = True xs = and (zipWith (<=) xs (tail xs))
57
3.18.
Ejercicio 3.18. Denir la funcin igual_conjunto tal que igual_conjunto l1 l2 se verica si las listas l1 y l2 vistas como conjuntos son iguales Por ejemplo,
igual_conjunto_1 :: Eq a => [a] -> [a] -> Bool igual_conjunto_1 xs ys = subconjunto xs ys && subconjunto ys xs
2. Por recursin.
igual_conjunto_2 :: Eq a => [a] -> [a] -> Bool igual_conjunto_2 xs ys = aux (nub xs) (nub ys) where aux [] [] = True aux (x:_) [] = False aux [] (y:_) = False aux (x:xs) ys = x `elem` ys && aux xs (delete x ys)
3. Usando sort
igual_conjunto_3 :: (Eq a, Ord a) => [a] -> [a] -> Bool igual_conjunto_3 xs ys = sort (nub xs) == sort (nub ys)
3.19.
Ejercicio 3.19. Denir la funcin inserta tal que inserta e l inserta el elemento e en la lista l delante del primer elemento de l mayor o igual que e. Por ejemplo,
Se puede denir el generador de QuickCheck para que cree lista ordenadas y compruebe que inserta las mantiene ordenada
listaOrdenada :: Gen [Integer] listaOrdenada = do n <- arbitrary listaDesde n where listaDesde n = frequency [(1, return []),
59
(5, do i <- arbitrary ns <- listaDesde (n+abs i) return (n:ns))] prop_inserta x = forAll listaOrdenada $ \xs -> collect (length xs) $ lista_ordenada (inserta x xs)
En efecto,
Inserta> quickCheck prop_inserta OK, passed 100 tests. 18% 2. 16% 1. 10% 5. 10% 0. 9% 6. 7% 7. 7% 3. 4% 9. 4% 12. 3% 4. 2% 8. 2% 19. 2% 13. 1% 22. 1% 18. 1% 17. 1% 15. 1% 11. 1% 10.
3.20.
Ejercicio 3.20. Denir la funcin ordena_por_insercin tal que ordena_por_insercin l es la lista l ordenada mediante insercin, Por ejemplo,
60 1. Denicin recursiva
ordena_por_insercin_1 :: Ord a => [a] -> [a] ordena_por_insercin_1 [] = [] ordena_por_insercin_1 (x:xs) = inserta x (ordena_por_insercin_1 xs)
2. Denicin por plegado por la derecha
ordena_por_insercin_3 :: Ord a => [a] -> [a] ordena_por_insercin_3 = foldl (flip inserta) []
Las deniciones son equivalentes:
prop_equivalencia :: [Int] -> Bool prop_equivalencia xs = ordena_por_insercin_2 xs == ordena_por_insercin_1 xs && ordena_por_insercin_2 xs == ordena_por_insercin_1 xs
Comprobacin
Main> :set +s Main> ordena_por_insercin_1 [100,99..1] ,,, (51959 reductions, 68132 cells) Main> ordena_por_insercin_2 [100,99..1] ,,, (51960 reductions, 68034 cells) Main> ordena_por_insercin_3 [100,99..1] ... (3451 reductions, 5172 cells)
se observa que la tercera denicin es ms eciente. En los sucesivo usaremos como ordena_por_insercin la tercera
61
prop_ordena_por_insercin_ordenada :: [Int] -> Bool prop_ordena_por_insercin_ordenada xs = lista_ordenada (ordena_por_insercin xs) Ordena_por_insercion> quickCheck prop_ordena_por_insercin_ordenada OK, passed 100 tests.
3.21.
Ejercicio 3.21. Redenir la funcin minimum tal que minimum l es el menor elemento de la lista l. Por ejemplo,
minimum [3,2,5] ; 2
Solucin: Se presentan distintas deniciones: 1. Denicin recursiva:
n_minimum_1 :: Ord a => [a] -> a n_minimum_1 [x] = x n_minimum_1 (x:y:xs) = n_minimum_1 ((min x y):xs)
2. Denicin con plegado:
62
prop_equivalencia :: [Int] -> Property prop_equivalencia xs = not (null xs) ==> (n_minimum_1 xs == minimum xs && n_minimum_2 xs == minimum xs && n_minimum_3 xs == minimum xs )
Comprobacin
Main :set +s Main> n_minimum_1 1 (2644 reductions, Main> n_minimum_2 1 (2548 reductions, Main> n_minimum_3 1 (2552 reductions, minimum_3 minimum_3 minimum_3 minimum_3
[100,99..1] 3568 cells) [100,99..1] 3373 cells) [100,99..1] 3477 cells) ( 300 ( 2550 ( 25050 (250050 reductions, 416 cells) reductions, 3476 cells) reductions, 34076 cells) reductions, 340077 cells) ( 750 ( 51960 ( 5019060 (500190060 reductions, 1028 reductions, 68034 reductions, 6530485 reductions, 650313987 cells) cells) cells) cells)
3.22.
Ejercicio 3.22. Denir la funcin mezcla tal que mezcla l1 l2 es la lista ordenada obtenida al mezclar las listas ordenadas l1 y l2. Por ejemplo,
63
mezcla_1 :: Ord a => [a] mezcla_1 [] ys = mezcla_1 xs [] = mezcla_1 (x:xs) (y:ys) | x <= y = x | otherwise = y
mezcla_2 :: Ord a => [a] -> [a] -> [a] mezcla_2 [] ys = ys mezcla_2 (x:xs) ys = inserta x (mezcla_2 xs ys)
3. Usaremos como mezcla la primera
mezcla :: Ord a => [a] -> [a] -> [a] mezcla = mezcla_1
Las deniciones son equivalentes:
prop_mezcla_ordenada :: [Int] -> [Int] -> Property prop_mezcla_ordenada xs ys = lista_ordenada xs && lista_ordenada ys ==> lista_ordenada (mezcla xs ys)
Comprobacin
64
3.23.
Ejercicio 3.23. Denir la funcin ordena_por_m tal que ordena_por_m l es la lista l ordenada mediante mezclas, Por ejemplo,
ordena_por_m :: Ord a => [a] -> [a] ordena_por_m [] = [] ordena_por_m [x] = [x] ordena_por_m xs = mezcla (ordena_por_m ys) (ordena_por_m zs) where medio = (length xs) `div` 2 ys = take medio xs zs = drop medio xs
El valor de ordena_por_m es una lista ordenada
prop_ordena_por_m_ordenada :: [Int] -> Bool prop_ordena_por_m_ordenada xs = lista_ordenada (ordena_por_m xs) PD> quickCheck prop_ordena_por_m_ordenada OK, passed 100 tests.
3.24.
Ejercicio 3.24. Denir la funcin dgitoDeCarcter tal que dgitoDeCarcter c es el dgito correspondiente al carcter numrico c. Por ejemplo,
dgitoDeCarcter '3' ; 3
Solucin:
65
3.25.
Ejercicio 3.25. Denir la funcin carcterDeDgito tal que carcterDeDgito n es el carcter correspondiente al dgito n. Por ejemplo,
carcterDeDgito 3 ; '3'
Solucin:
prop_inversa ; True
3.26.
Ejercicio 3.26. Denir la funcin desde tal que desde n es la lista de los nmeros enteros a partir de n. Por ejemplo,
desde 5
; [5,6,7,8,9,10,11,12,13,14,{Interrupted!}
66
prop_equivalencia :: Int -> Int -> Bool prop_equivalencia n m = take m (desde_1 n) == take m (desde_2 n)
Comprobacin
3.27.
Ejercicio 3.27. Redenir la funcin repeat tal que repeat x es una lista innita con el nico elemento x. Por ejemplo,
prop_equivalencia :: Int -> Int -> Bool prop_equivalencia n m = take n (n_repeat_1 m) == take n (repeat m) && take n (n_repeat_2 m) == take n (repeat m) && take n (n_repeat_3 m) == take n (repeat m)
Comprobacin
67
3.28.
Ejercicio 3.28. Redenir la funcin replicate tal que replicate n x es una lista con n copias del elemento x. Por ejemplo,
:: Int n m = n m == n m == n m ==
68
3.29.
Ejercicio 3.29. Redenir la funcin iterate tal que iterate f x es la lista cuyo primer elemento es x y los siguientes elementos se calculan aplicando la funcin f al elemento anterior. Por ejemplo,
iterate (+1) 3 ; [3,4,5,6,7,8,9,10,11,12,{Interrupted!} iterate (*2) 1 ; [1,2,4,8,16,32,64,{Interrupted!} iterate (`div` 10) 1972 ; [1972,197,19,1,0,0,0,0,0,0,{Interrupted!}
Solucin:
prop_equivalencia :: Int -> Int -> Bool prop_equivalencia n m = take n (n_iterate (+1) m) == take n (iterate (+1) m)
Comprobacin
3.30.
Ejercicio 3.30. Denir la funcin deEnteroACadena tal que deEnteroACadena n es la cadena correspondiente al nmero entero n. Por ejemplo,
deEnteroACadena_1 :: Int -> String deEnteroACadena_1 = map carcterDeDgito . reverse . map (`rem` 10) . takeWhile (/= 0) . iterate (`div` 10)
69
iterate (`div` 10) 1972 ; [1972,197,19,1,0,0,0,... (takeWhile (/= 0) . iterate (`div` 10)) 1972 ; [1972,197,19,1] map (`rem` 10) [1972,197,19,1] ; [2,7,9,1] reverse [2,7,9,1] ; [1,9,7,2] map carcterDeDgito [1,9,7,2] ; "1972"
2. Mediante la funcin show
3.31.
Ejercicio 3.31. Denir la funcin primos_por_criba tal que primos_por_criba es la lista de los nmeros primos mediante la criba de Erasttenes.
primos_por_criba_1 :: [Int] primos_por_criba_1 = map head (iterate eliminar [2..]) where eliminar (x:xs) = filter (no_multiplo x) xs no_multiplo x y = y `mod` x /= 0
Para ver el clculo, consideramos la siguiente variacin
70
primos_por_criba_1_aux = map (take 10) (iterate eliminar [2..]) where eliminar (x:xs) = filter (no_multiplo x) xs no_multiplo x y = y `mod` x /= 0
Entonces,
primos_por_criba_2 :: [Int] primos_por_criba_2 = criba [2..] where criba (p:xs) = p : criba [n | n<-xs, n `mod` p /= 0]
Las deniciones son equivalentes:
3.32.
todosPares xs se verica si todos los elementos de la lista xs son pares. Por ejemplo, todosPares [2,4,6] ; True todosPares [2,4,6,7] ; False
Solucin: Se presentan distintas deniciones:
3.33. Comprobacin de que todos los elementos son impares 1. Denicin recursiva:
71
todosPares_1 :: [Int] -> Bool todosPares_1 [] = True todosPares_1 (x:xs) = even x && todosPares_1 xs
2. Denicin con all:
prop_equivalencia :: [Int] -> Bool prop_equivalencia xs = todosPares_2 xs == todosPares_1 xs && todosPares_3 xs == todosPares_1 xs
Comprobacin
3.33.
todosImpares xs se verica si todos los elementos de la lista xs son impares. Por ejemplo, todosImpares [1,3,5] ; True todosImpares [1,3,5,6] ; False
Solucin: Se presentan distintas deniciones: 1. Denicin recursiva:
72
todosImpares_1 :: [Int] -> Bool todosImpares_1 [] = True todosImpares_1 (x:xs) = odd x && todosImpares_1 xs
2. Denicin con all:
prop_equivalencia :: [Int] -> Bool prop_equivalencia xs = todosImpares_2 xs == todosImpares_1 xs && todosImpares_3 xs == todosImpares_1 xs
Comprobacin
3.34.
Tringulos numricos
Ejercicio 3.34. Denir la funcin tringulo tal que tringulo n es la lista de las lista de nmeros consecutivos desde [1] hasta [1,2,...,n. Por ejemplo,
tringulo 4 ; [[1],[1,2],[1,2,3],[1,2,3,4]]
Solucin: Denicin por comprensin:
73
3.35.
Ejercicio 3.35. Denir la funcin posicin tal que posicin x ys es la primera posicin del elemento x en la lista ys y 0 en el caso de que no pertenezca a la lista. Por ejemplo,
posicin 5 [1,5,3,5,6,5,3,4] ; 2
Solucin: Se presentan distintas deniciones: 1. Denicin recursiva:
posicin_1 :: Eq a => a -> [a] -> Int posicin_1 x ys = if elem x ys then aux x ys else 0 where aux x [] = 0 aux x (y:ys) | x== y = 1 | otherwise = 1 + aux x ys
2. Denicin con listas de comprensin:
posicin_2 :: Eq a => a -> [a] -> Int posicin_2 x xs = head ([pos | (y,pos) <- zip xs [1..length xs], y == x] ++ [0])
Las deniciones son equivalentes:
74
prop_posicin :: Int -> [Int] -> Bool prop_posicin x xs = let n=posicin x xs in if n==0 then notElem x xs else xs!!(n-1)==x
3.36.
Ordenacin rpida
Ejercicio 3.36. Denir la funcin ordenaR tal que ordenaR xs es la lista xs ordenada mediante el procedimiento de ordenacin rpida. Por ejemplo,
ordenaR :: Ord a => [a] -> [a] ordenaR [] = [] ordenaR (x:xs) = ordenaR menores ++ [x] ++ ordenaR mayores where menores = [e | e<-xs, e<x] mayores = [e | e<-xs, e>=x]
El valor de ordenaR es una lista ordenada
prop_ordenaR_ordenada :: [Int] -> Bool prop_ordenaR_ordenada xs = lista_ordenada (ordenaR xs) Ordena_por_insercion> quickCheck prop_ordenaR_ordenada OK, passed 100 tests.
3.37.
Ejercicio 3.37. Redenir la funcin fst tal que fst p es la primera componente del par p. Por ejemplo,
fst (3,2) ; 3
Solucin:
75
3.38.
Ejercicio 3.38. Redenir la funcin snd tal que snd p es la segunda componente del par p. Por ejemplo,
snd (3,2) ; 2
Solucin:
76
3.39.
fst3 t es la primera componente de la terna t. snd3 t es la segund componente de la terna t. thd3 t es la tercera componente de la terna t.
Por ejemplo,
n_fst3 :: (a,b,c) -> a n_fst3 (x,_,_) = x n_snd3 :: (a,b,c) -> b n_snd3 (_,y,_) = y n_thd3 :: (a,b,c) -> c n_thd3 (_,_,z) = z
Se verica la siguiente propiedad:
3.40.
Ejercicio 3.40. Denir la funcin variable tal que variable p es la cadena correspondiente al par p formado por un carcter y un nmero. Por ejemplo,
77
3.41.
Ejercicio 3.41. Redenir la funcin splitAt tal que splitAt n l es el par formado por la lista de los n primeros elementos de la lista l y la lista l sin los n primeros elementos. Por ejemplo,
:: Int -> [a] -> ([a], [a]) n xs | n <= 0 = ([],xs) _ [] = ([],[]) n (x:xs) = (x:xs',xs'') (xs',xs'') = n_splitAt (n-1) xs
prop_splitAt :: Int -> [Int] -> Bool prop_splitAt n xs = n_splitAt n xs == (take n xs, drop n xs)
Comprobacin
3.42.
Sucesin de Fibonacci
Ejercicio 3.42. Denir la funcin fib n tal que fib n es el nsimo trmino de la sucesin de Fibonacci 1,1,2,3,5,8,13,21,34,55,. . . Por ejemplo,
fib 5
valor
78
fib_2 :: Int -> Int fib_2 n = fib_2_aux n 1 1 where fib_2_aux 0 p q = p fib_2_aux (n+1) p q = fib_2_aux n q (p+q)
3. Denicin con mediante listas innitas:
fibs :: [Int] fibs = 1 : 1 : [a+b | (a,b) <- zip fibs (tail fibs)]
Las deniciones son equivalentes:
prop_equivalencia :: Bool prop_equivalencia = [fib_1 n | n <- [1..20]] == [fib_2 n | n <- [1..20]] && [fib_3 n | n <- [1..20]] == [fib_2 n | n <- [1..20]]
Comprobacin
79
3.43.
Ejercicio 3.43. Denir la funcin incmin tal que incmin l es la lista obtenida aadiendo a cada elemento de l el menor elemento de l. Por ejemplo,
incmin_1 :: [Int] -> [Int] incmin_1 l = map (+e) l where e = mnimo l mnimo [x] = x mnimo (x:y:xs) = min x (mnimo (y:xs))
2. Con la denicin anterir se recorre la lista dos veces: una para calcular el mnimo y otra para sumarlo. Con la siguiente denicin la lista se recorre slo una vez.
incmin_2 :: [Int] -> [Int] incmin_2 [] = [] incmin_2 l = nuevalista where (minv, nuevalista) = un_paso l un_paso [x] = (x, [x+minv]) un_paso (x:xs) = (min x y, (x+minv):ys) where (y,ys) = un_paso xs
Las deniciones son equivalentes:
80
3.44.
Ejercicio 3.44. Denir el tipo Punto como un par de nmeros reales Por ejemplo,
(3.0,4.0) :: Punto
Solucin:
distancia :: Punto -> Punto -> Double distancia (x,y) (x',y') = sqrt((x-x')^2+(y-y')^2)
Ejercicio 3.47. Denir el tipo Camino como una lista de puntos Por ejemplo,
[(1,2),(4,6),(7,10)] :: Camino
Solucin:
81
longitud_camino_1 :: Camino -> Double longitud_camino_1 (x:y:xs) = distancia x y + longitud_camino_1 (y:xs) longitud_camino_1 _ = 0
2. Denicin por comprensin:
longitud_camino_2 :: Camino -> Double longitud_camino_2 xs = sum [distancia p q | (p,q) <- zip (init xs) (tail xs)]
Evaluacin paso a paso:
longitud_camino_2 [(1,2),(4,6),(7,10)] = sum [distancia p q | (p,q) <- zip (init [(1,2),(4,6),(7,10)]) (tail [(1,2),(4,6),(7,10)])] = sum [distancia p q | (p,q) <- zip [(1,2),(4,6)] [(4,6),(7,10)]] = sum [distancia p q | (p,q) <- [((1,2),(4,6)),((4,6),(7,10))]] = sum [5.0,5.0] = 10
Las deniciones son equivalentes:
prop_equivalencia xs = not (null xs) ==> longitud_camino_1 xs ~= longitud_camino_2 xs infix 4 ~= (~=) :: Double -> Double -> Bool x ~= y = abs(x-y) < 0.0001
Comprobacin
3.45.
Solucin:
Nmeros racionales
Ejercicio 3.49. Denir el tipo Racional de los nmeros racionales como pares de enteros.
82
; ; ; ;
; ; ; ;
Solucin:
qMul :: Racional -> Racional -> Racional qMul (x1,y1) (x2,y2) = simplificar (x1*x2, y1*y2) qDiv :: Racional -> Racional -> Racional qDiv (x1,y1) (x2,y2) = simplificar (x1*y2, y1*x2) qSum :: Racional -> Racional -> Racional qSum (x1,y1) (x2,y2) = simplificar (x1*y2+y1*x2, y1*y2) qRes :: Racional -> Racional -> Racional qRes (x1,y1) (x2,y2) = simplificar (x1*y2-y1*x2, y1*y2)
Ejercicio 3.52. Denir la funcin escribeRacional tal que escribeRacional x es la cadena correspodiente al nmero racional x. Por ejemplo,
escribeRacional (10,12) ; "5/6" escribeRacional (12,12) ; "1" escribeRacional (qMul (1,2) (2,3)) ; "1/3"
83
escribeRacional :: Racional -> String escribeRacional (x,y) | y' == 1 = show x' | otherwise = show x' ++ "/" ++ show y' where (x',y') = simplificar (x,y)
3.46.
Ejercicio 3.53. Redenir la funcin gcd tal que gcd x y es el mximo comn divisor de x e y. Por ejemplo,
gcd 6 15 ; 3
Solucin: Se presentan distintas deniciones: 1. Denicin recursiva:
n_gcd_1 :: Int -> Int -> Int n_gcd_1 0 0 = error "gcd 0 0 no est definido" n_gcd_1 x y = n_gcd_1' (abs x) (abs y) where n_gcd_1' x 0 = x n_gcd_1' x y = n_gcd_1' y (x `rem` y)
2. Denicin con divisible y divisores
:: Int -> Int -> Int 0 0 = error "gcd 0 0 no est definido" 0 y = abs y x y = last (filter (divisible y') (divisores x')) where x' = abs x y' = abs y divisores x = filter (divisible x) [1..x] divisible x y = x `rem` y == 0
prop_equivalencia :: Int -> Int -> Property prop_equivalencia x y = (x,y) /= (0,0) ==> n_gcd_1 x y == gcd x y && n_gcd_2 x y == gcd x y
84 Comprobacin
3.47.
Ejercicio 3.54. Redenir la funcin lookup tal que lookup l z es el valor del primer elemento de la lista de bsqueda l cuya clave es z. Por ejemplo,
n_lookup :: Eq a => a -> [(a,b)] -> Maybe b n_lookup k [] = Nothing n_lookup k ((x,y):xys) | k==x = Just y | otherwise = n_lookup k xys
Las deniciones son equivalentes:
prop_equivalencia :: Int -> [(Int,Int)] -> Bool prop_equivalencia z xys = n_lookup z xys == n_lookup z xys
Comprobacin
prop_lookup :: Int -> Int -> [(Int,Int)] -> Bool prop_lookup x y xys = if n_lookup x xys == Just y then elem (x,y) xys else notElem (x,y) xys
Sin embargo, no es cierta la siguiente
:: Int -> Int -> [(Int,Int)] -> Bool x y xys = xys then n_lookup x xys == Just y x xys == Nothing
85
3.48.
Ejercicio 3.55. Redenir la funcin zip tal que zip x y es la lista obtenida emparejando los correspondientes elementos de x e y. Por ejemplo,
n_zip_1 :: [a] -> [b] -> [(a,b)] n_zip_1 (x:xs) (y:ys) = (x,y) : zip xs ys n_zip_1 _ _ = []
2. Denicin con zipWith
n_zip_2 :: [a] -> [b] -> [(a,b)] n_zip_2 = zipWith (\x y -> (x,y))
Las deniciones son equivalentes:
:: xs == ==
86
3.49.
Ejercicio 3.56. Redenir la funcin zipWith tal que zipWith f x y es la lista obtenida aplicando la funcin f a los elementos correspondientes de las listas x e y. Por ejemplo,
zipWith (+) [1,2,3] [4,5,6] ; [5,7,9] zipWith (*) [1,2,3] [4,5,6] ; [4,10,18]
Solucin:
3.50.
Curricacin
Ejercicio 3.57. Una funcin est en forma cartesiana si su argumento es una tupla. Por ejemplo,
curry suma_cartesiana 2 3 ; 5
87
y la funcin uncurry tal que uncurry f es la versin cartesiana de la funcin f. Por ejemplo,
n_curry :: ((a,b) -> c) -> (a -> b -> c) n_curry f x y = f (x,y) n_uncurry :: (a -> b -> c) -> ((a,b) -> c) n_uncurry f p = f (fst p) (snd p)
3.51.
Ejercicio 3.58. Un rbol de tipo a es una hoja de tipo a o es un nodo de tipo a con dos hijos que son rboles de tipo a. Denir el tipo rbol. Solucin:
Solucin:
88
1 3 5 7
Ejercicio 3.60. Denir la funcin tamao tal que tamao a es el tamao del rbol a; es decir, el nmero de nodos internos. Por ejemplo,
tamao ejrbol_1 ; 7
Solucin:
tamao :: rbol a -> Int tamao Hoja = 0 tamao (Nodo x a1 a2) = 1 + tamao a1 + tamao a2
Ejercicio 3.61. Un rbol de bsqueda es un rbol binario en el que que todos los valores en el subrbol izquierdo son menores que el valor en el nodo mismo, y que todos los valores en el subrbol derecho son mayores. Por ejemplo, el ejrbol_1 es un rbol de bsqueda. Denir la funcin elemrbol tal que elemrbol e x se verica si e es un elemento del rbol de bqueda x. Por ejemplo,
elemrbol :: Ord a => a -> rbol a -> elemrbol e Hoja = False elemrbol e (Nodo x izq der) | e==x = | e<x = | e>x =
Ejercicio 3.62. Denir la funcin insertarbol tal que insertarbol e ab inserta el elemento e en el rbol de bsqueda ab. Por ejemplo,
89
(Nodo 7 Hoja (Nodo 8 Hoja Hoja))) Main> insertarbol 3 ejrbol_1 Nodo 4 (Nodo 2 (Nodo 1 Hoja Hoja) (Nodo 3 (Nodo 3 Hoja Hoja) Hoja)) (Nodo 6 (Nodo 5 Hoja Hoja) (Nodo 7 Hoja Hoja))
Solucin:
:: Ord a => a -> rbol a -> rbol a e Hoja = Nodo e Hoja Hoja e (Nodo x izq der) = Nodo x (insertarbol e izq) der = Nodo x izq (insertarbol e der)
Ejercicio 3.63. Denir la funcin listarbol tal que listarbol l es el rbol de bsqueda obtenido a partir de la lista l. Por ejemplo,
Main> listarbol [3,2,4,1] Nodo 1 Hoja (Nodo 4 (Nodo 2 Hoja (Nodo 3 Hoja Hoja)) Hoja)
Solucin:
listarbol :: Ord a => [a] -> rbol a listarbol = foldr insertarbol Hoja
Ejercicio 3.64. Denir la funcin aplana tal que aplana ab es la lista obtenida aplanando el rbol ab. Por ejemplo,
90 Solucin:
aplana :: rbol a -> [a] aplana Hoja = [] aplana (Nodo x izq der) = aplana izq ++ [x] ++ aplana der
Ejercicio 3.65. Denir la funcin ordenada_por_rbol tal que ordenada_por_rbol l es la lista l ordenada mediante rbol de bsqueda. Por ejemplo,
3.52.
Ejercicio 3.66. Denir la funcin elem_ord tal que elem_ord e l se verica si e es un elemento de la lista ordenada l. Por ejemplo,
elem_ord :: Ord a => a -> [a] -> Bool elem_ord _ [] = False elem_ord e (x:xs) | x < e = elem_ord e xs | x == e = True | otherwise = False
91
3.53.
Ejercicio 3.67. Denir el tipo nito Direccim tal que sus constructores son Norte, Sur, Este y Oeste. Solucin:
:: Direccin -> (Int,Int) -> (Int,Int) Norte (x,y) = (x,y+1) Sur (x,y) = (x,y-1) Este (x,y) = (x+1,y) Oeste (x,y) = (x-1,y)
3.54.
Ejercicio 3.69. Denir el tipo de datos Ratio para representar los racionales como un par de enteros (su numerador y denominador). Solucin:
data Ratio =
Ejercicio 3.70. Denir Ratio como una instancia de Show de manera que la funcin show muestra la forma simplicada obtenida mediante la funcin simplificarRatio tal que simplificarRatio x es el nmero racional x simplicado. Por ejemplo,
92
instance Show Ratio where show (Rac x 1) = show x show (Rac x y) = show x' ++ "/" ++ show y' where (Rac x' y') = simplificarRatio (Rac x y) simplificarRatio :: Ratio -> Ratio simplificarRatio (Rac n d) = Rac (((signum d)*n) `div` m) ((abs d) `div` m) where m = gcd n d
Ejercicio 3.71. Denir los nmeros racionales 0, 1, 2, 3, 1/2, 1/3 y 1/4. Por ejemplo,
= = = = = = =
0 1 2 3 1 1 1
1 1 1 1 2 3 4
Ejercicio 3.72. Denir las operaciones entre nmeros racionales rMul, rDiv, rSum y rRes. Por ejemplo,
1 1 1 1
2) 2) 2) 2)
2 1 3 3
3) 4) 4) 4)
Solucin:
rMul :: Ratio -> Ratio -> Ratio rMul (Rac a b) (Rac c d) = simplificarRatio (Rac (a*c) (b*d)) rDiv :: Ratio -> Ratio -> Ratio rDiv (Rac a b) (Rac c d) = simplificarRatio (Rac (a*d) (b*c))
93
rSum :: Ratio -> Ratio -> Ratio rSum (Rac a b) (Rac c d) = simplificarRatio (Rac (a*d+b*c) (b*d)) rRes :: Ratio -> Ratio -> Ratio rRes (Rac a b) (Rac c d) = simplificarRatio (Rac (a*d-b*c) (b*d))
94
4.1.
Segmentos iniciales
Ejercicio 4.1. Denir la funcin iniciales tal que iniciales l es la lista de los segmentos iniciales de la lista l. Por ejemplo,
iniciales :: [a] -> [[a]] iniciales [] = [[]] iniciales (x:xs) = [] : [x:ys | ys <- iniciales xs]
95
96
4.2.
Segmentos nales
Ejercicio 4.2. Denir la funcin finales tal que finales l es la lista de los segmentos nales de la lista l. Por ejemplo,
finales :: [a] -> [[a]] finales [] = [[]] finales (x:xs) = (x:xs) : finales xs
El nmero de los segmentos nales es el nmero de los elementos de la lista ms uno.
4.3. Segmentos
97
4.3.
Segmentos
Ejercicio 4.3. Denir la funcin segmentos tal que segmentos l es la lista de los segmentos de la lista l. Por ejemplo,
segmentos :: [a] -> [[a]] segmentos [] = [[]] segmentos (x:xs) = segmentos xs ++ [x:ys | ys <- iniciales xs]
4.4.
Sublistas
Ejercicio 4.4. Denir la funcin sublistas tal que sublistas l es la lista de las sublistas de la lista l. Por ejemplo,
Main> sublistas [2,3,4] [[2,3,4],[2,3],[2,4],[2],[3,4],[3],[4],[]] Main> sublistas [1,2,3,4] [[1,2,3,4],[1,2,3],[1,2,4],[1,2],[1,3,4],[1,3],[1,4],[1], [2,3,4], [2,3], [2,4], [2], [3,4], [3], [4], []]
Solucin:
sublistas :: [a] -> [[a]] sublistas [] = [[]] sublistas (x:xs) = [x:ys | ys <- sub] ++ sub where sub = sublistas xs
4.5.
Comprobacin de subconjunto
Ejercicio 4.5. Denir la funcin subconjunto tal que subconjunto xs ys se verica si xs es un subconjunto de ys. Por ejemplo,
98
subconjunto_1 :: Eq a => [a] -> [a] -> Bool subconjunto_1 [] _ = True subconjunto_1 (x:xs) ys = elem x ys && subconjunto_1 xs ys
2. Denicin mediante all:
subconjunto_2 :: Eq a => [a] -> [a] -> Bool subconjunto_2 xs ys = all (`elem` ys) xs
3. Usaremos como subconjunto la primera
4.6.
Ejercicio 4.6. Denir la funcin igual_conjunto tal que igual_conjunto l1 l2 se verica si las listas l1 y l2 vistas como conjuntos son iguales Por ejemplo,
igual_conjunto_1 :: Eq a => [a] -> [a] -> Bool igual_conjunto_1 xs ys = subconjunto xs ys && subconjunto ys xs
99
igual_conjunto_2 :: Eq a => [a] -> [a] -> Bool igual_conjunto_2 xs ys = aux (nub xs) (nub ys) where aux [] [] = True aux (x:_) [] = False aux [] (y:_) = False aux (x:xs) ys = x `elem` ys && aux xs (delete x ys)
3. Usando sort
igual_conjunto_3 :: (Eq a, Ord a) => [a] -> [a] -> Bool igual_conjunto_3 xs ys = sort (nub xs) == sort (nub ys)
4. Usaremos como igual_conjunto la primera
4.7.
Permutaciones
Ejercicio 4.7. Denir la funcin permutaciones tal que permutaciones l es la lista de las permutaciones de la lista l. Por ejemplo,
import Data.List ((\\)) permutaciones_1 :: Eq a => [a] -> [[a]] permutaciones_1 [] = [[]] permutaciones_1 xs = [a:p | a <- xs, p <- permutaciones_1(xs \\ [a])]
2. Por recursin e intercalacin:
permutaciones_2 :: [a] -> [[a]] permutaciones_2 [] = [[]] permutaciones_2 (x:xs) = [zs | ys <- permutaciones_2 xs, zs <- intercala x ys]
donde intercala x ys es la lista de las listas obtenidas intercalando x entre los elementos de la lista l. Por ejemplo,
intercala 1 [2,3] ; [[1,2,3],[2,1,3],[2,3,1]] intercala :: a -> [a] -> [[a]] intercala e [] = [[e]] intercala e (x:xs) = (e:x:xs) : [(x:ys) | ys <- (intercala e xs)]
Las deniciones son equivalentes:
prop_equivalencia :: [Int] -> Property prop_equivalencia xs = length xs <= 6 ==> igual_conjunto (permutaciones_1 xs) (permutaciones_2 xs)
Comprobacin
prop_nmero_permutaciones :: [Int] -> Property prop_nmero_permutaciones xs = length xs <= 6 ==> length (permutaciones_2 xs) == factorial (length xs) where factorial n = product [1..n]
4.8. Combinaciones
101
En la propiedades hemos acotado la longitude mxima de las listas generadas para facilitar los clculos. La segunda denicin es ms eciente: n permutaciones_1 permutaciones_2 2 140 102 3 334 172 4 1.170 428 5 5.656 1.740 6 34.192 10.036 7 243.744 71.252 donde las columnas segunda y tercera contiene el nmero de reducciones.
4.8.
Combinaciones
Ejercicio 4.8. Denir la funcin combinaciones tal que combinaciones n l es la lista de las combinaciones narias de la lista l. Por ejemplo,
combinaciones_1 :: Int -> [a] -> [[a]] combinaciones_1 n xs = [ys | ys <- sublistas xs, length ys == n]
2. Denicin directa:
:: Int -> [a] -> [[a]] 0 _ = [[]] _ [] = [] (n+1) (x:xs) = [x:ys | ys <- combinaciones_2 n xs] ++ combinaciones_2 (n+1) xs
Main> :set +s Main> length (combinaciones_1 2 [1..15]) 105 (1917964 reductions, 2327983 cells, 3 garbage collections) Main> length (combinaciones_2 2 [1..15]) 105 (6217 reductions, 9132 cells)
102
4.9.
Ejercicio 4.9. El problema de las N reinas consiste en colocar N reinas en un tablero rectangular de dimensiones N por N de forma que no se encuentren ms de una en la misma lnea: horizontal, vertical o diagonal. Denir la funcin reinas tal que reinas n es la lista de las soluciones del problema de las N reinas. Por ejemplo,
reinas 4 ; [[3,1,4,2],[2,4,1,3]]
La primera solucin [3,1,4,2] se interpreta como R R R R Solucin: Se importa la diferencia de conjuntos (\\) del mdulo List:
reinas :: Int -> [Tablero] reinas n = reinasAux n where reinasAux 0 = [[]] reinasAux (m+1) = [r:rs | rs <- reinasAux m, r <- ([1..n] \\ rs), noAtaca r rs 1]
donde noAtaca r rs d se verica si la reina r no ataca a niguna de las de la lista rs donde la primera de la lista est a una distancia horizontal d.
noAtaca :: Int -> Tablero -> Int -> Bool noAtaca _ [] _ = True noAtaca r (a:rs) distH = abs(r-a) /= distH && noAtaca r rs (distH+1)
103
4.10.
Nmeros de Hamming
Ejercicio 4.10. Los nmeros de Hamming forman una sucesin estrictamente creciente de nmeros que cumplen las siguientes condiciones: 1. El nmero 1 est en la sucesin. 2. Si x est en la sucesin, entonces 2 x, 3 x y 5 x tambin estn. 3. Ningn otro nmero est en la sucesin. Denir la funcin hamming tal que hamming es la sucesin de Hamming. Por ejemplo,
hamming :: [Int] hamming = 1 : mezcla3 [2*i | i <- hamming] [3*i | i <- hamming] [5*i | i <- hamming]
donde mezcla3 xs ys zs es la lista obtenida mezclando las listas ordenadas xs, ys y zs y eliminando los elementos duplicados. Por ejemplo,
mezcla3 [2,4,6,8,10] [3,6,9,12] [5,10] ; [2,3,4,5,6,8,9,10,12] mezcla3 :: [Int] -> [Int] -> [Int] -> [Int] mezcla3 xs ys zs = mezcla2 xs (mezcla2 ys zs)
y mezcla2 xs ys zs es la lista obtenida mezclando las listas ordenadas xs e ys y eliminando los elementos duplicados. Por ejemplo,
mezcla2 [2,4,6,8,10,12] [3,6,9,12] ; [2,3,4,6,8,9,10,12] mezcla2 :: [Int] -> [Int] -> [Int] mezcla2 p@(x:xs) q@(y:ys) | x < y | x > y | otherwise mezcla2 [] ys mezcla2 xs [] = = = = = x:mezcla2 xs q y:mezcla2 p ys x:mezcla2 xs ys ys xs
104
Bibliografa
[1] H. C. Cunningham. Notes on functional programming with haskell. Technical report, University of Mississippi, 2007. [2] J. Fokker. Programacin funcional. Technical report, Universidad de Utrech, 1996. [3] B. C. Ruiz, F. Gutirrez, P. Guerrero, and J. Gallardo. Razonando con Haskell (Un curso sobre programacin funcional). Thompson, 2004. [4] S. Thompson. Haskell: The Craft of Functional Programming. AddisonWesley, second edition, 1999. En Bib. [5] E. P. Wentworth. Introduction to Funcional Programming. Technical report, Parallel Processing Group. Rhodes University, 1994.
105
ndice alfabtico
Camino, 80 Direccin, 91 Punto, 80 Racional, 81 Ratio, 91 &&&, 15 rbol, 87 =, 20 anterior_1, 15 anterior_2, 15 aplana, 90 arco_coseno_1, 39 arco_coseno_2, 40 arco_seno_1, 39 arco_seno_2, 40 carcterDeDgito, 65 combinaciones_1, 101 combinaciones_2, 101 comb, 9 compuesta, 34 concat_1, 44 concat_2, 44 concat_3, 44 conc, 43 cuadrado_1, 11 cuadrado_2, 11 cuadrado_3, 11 da, 36 dgitoDeCarcter, 64 deEnteroACadena_1, 68 deEnteroACadena_2, 69 derivadaBurda, 38 derivadaFinaDelSeno, 38 derivadaFina, 38 derivadaSuper, 38 derivada, 38 desde_1, 65 desde_2, 65 distancia_al_origen, 80 distancia, 80 divisible, 34 divisores_1, 35 divisores_2, 35 divisores, 35 doble_1, 21 doble_2, 21 doble_3, 21 dosElevadoA_1, 24 dosElevadoA_2, 24 dosElevadoA_3, 24 ejrbol_1, 87 elemrbol, 88 elem_ord, 90 esPositivo_1, 24 esPositivo_2, 25 esPositivo_3, 25 escribeRacional, 83 fact1, 8 fact2, 8 fact3, 8 fact4, 8 fact5, 8 fact6, 8 factoriales_1, 31 factoriales_2, 32 factoriales_3, 32
106
ndice alfabtico
107
factoriales_4, 32 factoriales_5, 32 factorial, 9 fib_1, 77 fib_2, 78 fib_3, 78 finales, 96 flip, 34 igualLista, 43 igual_conjunto_1, 57, 98 igual_conjunto_2, 57, 99 igual_conjunto_3, 57, 99 impar1, 10 impar2, 10 impar3, 10 impar4, 10 incmin_1, 79 iniciales, 95 insertarbol, 89 inserta, 58 inversa, 40 inverso_1, 23 inverso_2, 23 inverso_3, 23 listarbol, 89 lista_ordenada_1, 56 lista_ordenada_2, 56 lista_ordenada, 56 longitud_camino_1, 80 longitud_camino_2, 81 mezcla_1, 63 mezcla_2, 63 mezcla, 63 mitad_1, 22 mitad_2, 22 mitad_3, 22 mueve, 91 n_abs_1, 13 n_abs_2, 14 n_and_1, 28
n_and_2, 28 n_curry, 87 n_dropWhile, 50 n_drop, 49 n_elem_1, 53 n_elem_2, 53 n_elem_3, 53 n_elem_4, 53 n_elem_5, 54 n_elem_6, 54 n_filter_1, 26 n_filter_2, 26 n_foldl, 30 n_foldr, 30 n_fst3, 76 n_fst, 74 n_gcd_1, 83 n_gcd_2, 83 n_head, 45 n_id, 17 n_init_1, 47 n_init_2, 47 n_init_3, 47 n_iterate, 68 n_last_1, 45 n_last_2, 46 n_last_3, 46 n_last_4, 46 n_last_5, 46 n_length_1, 52 n_length_2, 52 n_length_3, 52 n_length_4, 52 n_lookup, 84 n_map_1, 25 n_map_2, 25 n_minimum_1, 61 n_minimum_2, 61 n_minimum_3, 61 n_notElem_1, 55
108
ndice alfabtico
n_notElem_2, 55 n_notElem_3, 55 n_notElem_4, 55 n_notElem_5, 55 n_notElem_6, 55 n_notElem_7, 54, 55 n_or_1, 29 n_or_2, 29 n_producto_1, 27 n_producto_2, 28 n_repeat_1, 66 n_repeat_2, 66 n_repeat_3, 66 n_replicate_1, 67 n_replicate_2, 67 n_replicate_3, 67 n_reverse_1, 51 n_reverse_2, 51 n_reverse_3, 51 n_scanr, 31 n_signum, 14 n_snd3, 76 n_snd, 75 n_splitAt, 77 n_sum_1, 27 n_sum_2, 27 n_tail, 45 n_take, 48 n_thd3, 76 n_uncurry, 87 n_until, 33 n_zipWith, 86 n_zip_1, 85 n_zip_2, 85 nth, 50 ordenaR, 74 ordena_por_insercin_1, 60 ordena_por_insercin_2, 60 ordena_por_insercin_3, 60 ordena_por_m, 64
ordenada_por_rbol, 90 permutaciones_1, 100 permutaciones_2, 100 posicin_1, 73 posicin_2, 73 potencia_1, 16 potencia_2, 16 primos_1, 36 primos_por_criba_1, 69 primos_por_criba_2, 70 primo, 35 puntoCero, 39 qDiv, 82 qMul, 82 qRes, 82 qSum, 82 rCero, 92 rCuarto, 92 rDiv, 92 rDos, 92 rMedio, 92 rMul, 92 rRes, 92 rSum, 92 rTercio, 92 rTres, 92 rUno, 92 raz_cbica_1, 39 raz_cbica_2, 40 raz_cuadrada_1, 39 raz_cuadrada_2, 40 raices_1, 13 raices_2, 13 raizCuadrada, 39 reinas, 102 segmentos, 97 siguiente_1, 20 siguiente_2, 20 simplificarRatio, 91 simplificar, 82
ndice alfabtico
109
subconjunto_1, 98 subconjunto_2, 98 sublistas, 97 suma_de_cuadrados_1, 12 suma_de_cuadrados_2, 12 suma_de_cuadrados_3, 12 suma_de_cuadrados_4, 12 tamao, 88 todosImpares_1, 71 todosImpares_2, 72 todosImpares_3, 72 todosPares_1, 71 todosPares_2, 71 todosPares_3, 71 tringulo, 72 variable, 77