Вы находитесь на странице: 1из 9

Asignatura Informtica.

Curso 2012/13
Grado en Matemticas. Facultad de Ciencias
Universidad de Mlaga
Relacin de Ejercicios 4 @ Jos E. Gallardo

1

Para realizar estos ejercicios, crea primero un nuevo fichero con nombre Rel4.hs. Aade al principio de
tu fichero lo siguiente, reemplazando APELLIDOS con tus apellidos y NOMBRE con tu nombre (en ese
orden):
-------------------------------------------------------------------------------
-- Relacin de Ejercicios 4.
-- Informtica. Grado en Matemticas. UMA.
--
-- Alumno: APELLIDOS, NOMBRE
-------------------------------------------------------------------------------

import Char
import List
import Mates.Aleatorios
import Mates.Plot
import Test.QuickCheck

1. Demuestra por induccin sobre listas finitas que map es funtor, es decir, que verifica las siguientes
propiedades:
map id xs = xs
map (f . g) xs = (map f . map g) xs
donde
id :: a -> a
id x = x
es la funcin predefinida identidad.

2. En este ejercicio estudiamos como calcular la integral definida de una funcin f :: Double ->
Double, en un intervalo [a,b] usando la regla de los trapecios, segn la cual el rea bajo la curva de
f se aproxima mediante el rea de un trapecio:
() ( )
() ()



Para calcular el rea de un modo ms preciso, se suele usar la versin compuesta de la regla, en la
que se divide el intervalo [a,b] a integrar en varios subintervalos, cuyas reas se aproximan cada
una con la regla anterior. La aproximacin de la integral definida en el intervalo [a,b] ser la suma
de las reas de los distintos trapecios correspondientes a cada subintervalo. Por ejemplo, la
siguiente figura muestra como se ha aproximado la integral definida de la funcin en rojo en el
intervalo [-2,2] mediante la suma de las reas de 16 trapecios (en azul):



Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

2

a) Define una funcin recursiva inteDef f a b eps que aproxime la integral definida de la funcin
f en el intervalo [a,b] mediante la regla compuesta. Usa para ello un algoritmo del tipo divide y
vencers. El parmetro eps indica el tamao mximo de los subintervalos en los que se dividir el
intervalo [a,b]. As, si la amplitud del intervalo [a,b] es menor o igual a eps, la funcin devolver el
rea del trapecio correspondiente. En otro caso, dividir el intervalo [a,b] en dos subintervalos del
mismo ancho (la mitad del intervalo original), aproximar recursivamente la integral de ambos
intervalos y devolver su suma. Por ejemplo:
inteDef cos 0 (pi/2) 0.001 => 0.9999999509771441
inteDef (\x -> x) 0 5 0.001 => 12.5
inteDef (\x -> x^2) 0 5 0.001 => 41.666666977107525
b) El desarrollo de la regla compuesta da lugar a la siguiente expresin:
()

(
() ()

)
que permite aproximar la integral definida dividiendo el intervalo [a,b] en n subintervalos del
mismo ancho. Haz uso de una lista por comprensin y la funcin predefinida sum para definir una
funcin inteDef' f a b n que aproxime la integral definida de f con la frmula anterior. Por
ejemplo:
inteDef' cos 0 (pi/2) 1000 => 0.9999997943832334
inteDef' (\x -> x) 0 5 1000 => 12.499999999999998
inteDef' (\x -> x^2) 0 5 1000 => 41.666687500000016

3. La mediana de un conjunto de valores es aqul valor tal que el 50% de los valores del conjunto se
encuentra por debajo de l y el otro 50% se encuentra por encima. Si el nmero de valores es
impar, la mediana coincide con alguno de los valores, por ejemplo:
mediana [3,20,1,10,50] => 10
ya que el 1 y el 3 son menores a 10, y adems el 20 y el 50 son mayores a 10. Si el nmero de
valores es par, la mediana se define como la media aritmtica de los dos valores centrales del
conjunto. Por ejemplo:
mediana [3,20,1,10,50,15] => 12.5
ya que los elementos centrales son 10 y 15, y la media de stos es 12.5.
a) Escribe una funcin que, dada un lista de valores de tipo Double, devuelva la mediana.
Ayuda: prueba a ordenar los elementos de la lista y usa el operador predefinido !!, que permite
acceder al elemento que ocupa cierta posicin en una lista. Por ejemplo:
[3,20,1,10,50,15] !! 0 => 3
[3,20,1,10,50,15] !! 1 => 20
[3,20,1,10,50,15] !! 2 => 1
b) Escribe una propiedad p_mediana para comprobar con QuickCheck que para cualquier lista xs de
tipo Double, si ordenados la lista y tomamos los elementos en la primera mitad de la lista ordenada,
todos ellos son menores o iguales a la mediana de xs, y que los restantes elementos son mayores o
iguales a la mediana. Para comprobar que todos los elementos de una lista cumplen una propiedad
puedes usar la funcin predefinida all :: (a->Bool) -> [a] -> Bool:
all even [2,4,10] => True
all (>5) [2,4,10] => False
all (<20) [2,4,10] => True

4. En este ejercicio estudiamos la secuencia de Fibonacci.
a) Usando parmetros acumuladores, define una funcin recursiva fibs :: [Integer] que
devuelva una lista infinita con todos los trminos de la secuencia de Fibonacci. Para que la funcin
sea eficiente, usa dos acumuladores de modo que en cada llamada recursiva baste con realizar una
suma. Por ejemplo:

Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

3

take 10 fibs => [0,1,1,2,3,5,8,13,21,34]
take 18 fibs => [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597]
b) Define una funcin cociente que tome dos enteros y devuelva el cociente entero que se obtiene
al dividir el primer nmero multiplicado por un milln por el segundo, con lo cual puedes obtener
un cociente con seis cifras decimales exactas. Por ejemplo:
cociente 123 7 => 17571428
123 / 7 => 17.571428571428573
c) Define una funcin relaciones que tome una lista de enteros y devuelva una lista con los
cocientes que se obtienen al dividir (segn se ha definido en el apartado anterior) cada trmino de
la lista por su anterior (el segundo por el primero, el tercero por el segundo, etc.). Para ver cul es la
relacin entre trminos consecutivos de la secuencia de Fibonacci, evala la expresin
take 20 . relaciones . tail $ fibs
Hacia qu valor convergen estos cocientes? Ayuda: la divina proporcin se define como
( ) .

5. Usando parmetros acumuladores, define una funcin recursiva facts :: [Integer] que
devuelva una lista infinita con los factoriales de cada uno de los nmeros naturales, comenzando
por 0!. Para que la funcin sea eficiente, usa dos acumuladores de modo que en cada llamada
recursiva baste con realizar un producto y una suma. Por ejemplo:
take 10 facts => [1,1,2,6,24,120,720,5040,40320,362880]
Ayuda: observa que si tienes los valores n! y (n+1), puedes obtener los valores (n+1)! y (n+2)
realizando solamente una suma y un producto, ya que (n+1)! = (n+1) n! .

6. Supongamos que representamos el siguiente polinomio de grado n
()


mediante una lista de tipo Double de longitud n+1 con los coeficientes de todos los trminos del
polinomio, de menor a mayor grado:

.
Si alguno de los trminos no existe en el polinomio (es nulo), incluiremos un cero en su
correspondiente posicin en la lista.
La siguiente funcin
evalPoli :: [Double] -> Double -> Double
evalPoli xs p = sum $ zipWith (\x n -> x*p^n) xs [0..]
puede ser utilizada para evaluar un polinomio (representado con la lista xs) en el punto p. Por
ejemplo:
evalPoli [1,2,3] 5 => 86
ya que [1,2,3] es la representacin del polinomio ()

, y p(5) es 86.
a) Lee y entiende la definicin de la funcin evalPoli.
b) Define, usando parmetros acumuladores, una funcin recursiva evalPoli1 que tome como
parmetros una lista con los coeficientes de un polinomio y un punto (de tipo Double), y devuelva
el valor del polinomio en dicho punto. Comprueba la correccin de tu definicin con la siguiente
propiedad usando QuickCheck:
p_evalPoli1 xs p = length xs < 6 ==> evalPoli1 xs p ~= evalPoli xs p
donde
infix 4 ~=
(~=) :: Double -> Double -> Bool
x ~= y = abs (x-y) < epsilon
where epsilon = 1/1000

Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

4

c) Para un polinomio de grado n, cuntos productos realiza tu funcin al evaluarlo? cuntas sumas
se realizan en la evaluacin?. Si usas el operador potencia, cuenta cada potencia con exponente x
como x productos.
d) Observa que el polinomio ()

puede escribirse de
forma alternativa del siguiente modo: ()

), donde se
ha sacado factor comn x para los trminos cin grado mayor a cero. Si repetimos este proceso para
el trmino entre parntesis, obtenemos: ()

)).
Repitiendo este proceso un nmero suficiente de veces, llegamos al siguiente desarrollo ()

))), que se conoce como la frmula de Horner para evaluar un


polinomio. Define una funcin recursiva evalPoli2 que evale un polinomio siguiendo la frmula
de Horner. Por ejemplo:
evalPoli2 [1,2,3] 5 => 86
e) Para un polinomio de grado n, cuntos productos realiza evalPoli2 al evaluarlo? cuntas sumas
se realizan en la evaluacin? De los mtodos para evaluar polinomios estudiados en este problema,
cul es el ms eficiente?
f) Usando foldr, define una funcin evalPoli3 que evale un polinomio con la frmula de Horner,
es decir, completa la siguiente definicin:
evalPoli3 :: [Double] -> Double -> Double
evalPoli3 xs p = foldr ?????? ??? xs

7. El desarrollo en serie de Taylor alrededor del punto a de una funcin f de reales en reales
infinitamente derivable se define como:
()

()
()

( )


donde f
(n)
es la ensima derivada de f. Si a=0, entonces la serie se llama de Maclaurin. Estos
desarrollos son muy tiles, ya que tomando un nmero finito de trminos de la serie es posible
calcular una aproximacin a la funcin original. Por ejemplo, la serie de Maclaurin para la funcin
seno es:
()
()
()
( )


a) Define una funcin maclaurinSeno que tome como parmetro x y devuelva una lista infinita con
los valores de los trminos de la serie de Maclaurin para el seno de x. Define primero una variable
local nums que represente la lista infinita [x, -x
3
, x
5
, -x
7
, ], otra variable local denoms para la lista
[1!, 3!, 5!, 7!, ] y empareja ambas listas trmino a trmino con la divisin (puedes usar zipWith
(/) para calcular la lista final).
b) Define una funcin aproxSeno que tome como parmetros n y x, y devuelva la aproximacin al
seno de x que se obtiene sumando los n primeros trminos de la serie de Maclaurin para el seno.
c) Usando la biblioteca Mates.Plot, genera un grfico como el siguiente en el que se represente la
funcin predefinida sin de Haskell y aproxSeno con 2 y 4 trminos en el intervalo [-2, 2]

Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

5



Tal como estudiars en las asignaturas de Mtodos Numricos, en este caso es posible determinar
que el error cometido con la aproximacin de 4 trminos es menor que |x|
9
/9!, por lo que en el
intervalo -1<x<1 el error cometido por la aproximacin no es mayor a 0.000003.
d) La funcin ln(1+x) (donde ln es el logaritmo neperiano) puede ser desarrollada mediante la
siguiente serie de Maclaurin:
( )
()


que slo converge a la funcin original para |x|<1. Escribe funciones para representar este
desarrollo en series (de modo similar a los apartados anteriores) y genera una grfica como la
siguiente donde se compara el valor de la funcin log(1+x) (usando la funcin predefinda log de
Haskell) con las aproximaciones obtenidas con 2, 4 y 8 trminos de la serie.


8. La siguiente funcin puede ser usada para generar una secuencia infinita de nmeros
pseudoaleatorios entre 0 y 25 (ambos incluidos):
cdigos :: Semilla -> [Int]
cdigos s = aleatoriosR (0,25) s


Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

6

Por ejemplo:
Main> take 20 $ cdigos 0
[18,18,23,21,13,9,7,15,3,16,3,23,21,2,17,0,18,19,21,24]
Main> take 20 $ cdigos 1
[17,0,7,9,12,24,20,22,22,10,17,23,13,5,12,16,6,4,4,1]
Main> take 20 $ cdigos 2
[18,6,0,21,17,4,8,25,13,4,2,24,10,0,4,22,15,21,2,17]
Una propiedad interesante de las secuencias pseudoaleatorias es que siempre que usemos la
misma semilla obtendremos la misma secuencia de nmeros. Gracias a esta propiedad es posible
usar la funcin cdigos para cifrar textos. Para ello, proporcionaremos una clave y un texto. La
clave se usar como semilla, y a partir de sta se obtendr una secuencia de nmeros entre 0 y 25
que se usarn como desplazamientos (cclicos) para cifrar las distintas letras minsculas del texto,
de modo similar a como se hace en el cifrado Csar. Por ejemplo:
codifica 1 "pepe" => "gewn"
codifica 2 "pepe" => "hkpz"
As, en el primer ejemplo, la clave es 1, por lo que se ha generado la secuencia con semilla 1 que
empieza con [17,0,7,9... . Para cifrar el texto "pepe" se ha desplazado la primera p 17
unidades (obtenindose la letra g), la primera e 0 unidades (obtenindose la letra e), la segunda p 7
unidades (obtenindose la letra w) y la segunda e 9 unidades (obtenindose la letra n).
a) Define la funcin codifica, que dado un texto y la clave, cifre el texto con dicha clave tal como se
ha descrito.
b) Define la funcin descodifica, que dado un texto cifrado y la clave con la que fue cifrado
devuelva la cadena original (descifrada). Por ejemplo:
descodifica 1 "gewn" => "pepe"
c) Define una propiedad para verificar que si ciframos un texto con una clave y luego los desciframos
con la misma clave, acabamos obteniendo el texto original. Comprubala con QuickCheck.
d) Crees que sera fcil romper este mtodo tal como explicamos con el cifrado Csar?

9. En 1693 Samuel Pepys quera ganar una apuesta y escribi a Isaac Newton para preguntarle cul de
los siguientes sucesos tiene una mayor probabilidad de ocurrir:
I. Tirar seis dados y obtener al menos un seis
II. Tirar doce dados y obtener al menos dos seis
III. Tirar dieciocho dados y obtener al menos tres seis
Pepys pensaba que la tercera opcin era la ms probable, pero Newton le demostr que estaba
equivocado. En este ejercicio, vas a simular los tres sucesos para determinar el ms probable.
Para obtener una secuencia infinita de tiradas de dados a partir de una semilla, puedes usar la
siguiente funcin:
dados :: Semilla -> [Int]
dados s = aleatoriosDe [1..6] s
Cambiando la semilla, puedes simular distintos experimentos. Por ejemplo:
Main> take 20 (dados 0)
[1,5,2,6,6,6,6,4,4,3,6,6,6,5,6,3,5,4,6,3]
Main> take 20 (dados 1)
[4,5,2,4,3,5,3,5,5,5,2,2,2,4,1,5,3,1,1,6]
Main> take 20 (dados 2)
[5,1,3,2,4,1,1,4,2,1,3,3,5,1,3,3,2,4,3,6]
Main> take 20 (dados 3)
[3,3,1,2,1,1,4,5,2,2,4,5,6,5,4,5,1,4,5,2]


Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

7

a) Define una funcin prob1 que tome como parmetro un nmero de experimentos a realizar (n) y
devuelva la probabilidad del primer suceso. Para ello, define primero una funcin tiradas6 que
genere n tiradas, cada una de seis dados, utilizando semillas desde el valor 0 al n-1 y tomando los
seis primeros elementos de cada secuencia infinita:
Main> tiradas6 4
[[1,5,2,6,6,6],[4,5,2,4,3,5],[5,1,3,2,4,1],[3,3,1,2,1,1]]
De todas estas tiradas, cuenta los xitos, es decir, aquellas listas que incluyan al menos un nmero
seis (puede resultar til definir primero una funcin que cuente cuantas veces aparece un valor en
una lista). Por ltimo, para obtener la probabilidad del suceso, divide el nmero de xitos por el
nmero de pruebas realizadas (n). Esta divisin debe ser real, por lo que probablemente necesites
convertir enteros en reales usando la funcin fromIntegral:
fromIntegral (length [1..10]) / 2.5 => 4.0
Calcula una aproximacin a la probabilidad del primer suceso realizando 5000 experimentos.
b) Define funciones prob2 y prob3 para determinar la probabilidad de los otros sucesos, siguiendo un
proceso similar al apartado anterior. Realiza 5000 experimentos en cada caso y, como hizo Newton,
determina cul es el suceso ms probable de los tres.

10. El problema del cumpleaos. Supn que una serie de personas van entrando en una habitacin
(inicialmente vaca) una a una, hasta que hay dos personas en la habitacin que cumplen aos el
mismo da. En promedio, cuntas personas debern entrar en la habitacin para que se produzca
la coincidencia de cumpleaos?. Escribe un programa para determinar la solucin a este problema.
Dado que hay 365 das en un ao, puedes modelar los distintos cumpleaos como nmeros entre 1
y 365, por lo que puedes obtener una lista aleatoria infinita de personas (realmente una lista con los
cumpleaos de dichas personas) usando la siguiente funcin:
cumpleaos :: Semilla -> [Int]
cumpleaos s = aleatoriosDe [1..365] s
Un experimento consiste en ir sacando nmeros de la lista aleatoria hasta que se produzca una
repeticin y contar los nmeros que ha sido necesario sacar. Para controlar las repeticiones de
cumpleaos, puedes usar un parmetro acumulador (inicialmente la lista vaca), al que aadirs
cada nmero que saques de la lista aleatoria, hasta que haya una repeticin. Realiza el experimento
con distintas semillas, calcula el nmero de personas necesarias en cada experimento y obtn por
ltimo el promedio (media aritmtica) de dichos valores.

11. En otra variante del problema del cumpleaos, se trata de averiguar cul es la probabilidad de que
haya al menos dos personas con el mismo cumpleaos en un grupo de p personas. Un experimento
consistir en tomar una lista de p elementos con valores aleatorios entre 1 y 365. Se producir un
xito si en dicha lista hay al menos dos valores repetidos (dos personas con el mismo cumpleaos).
a) Define una funcin probCumple que tome dos parmetros correspondientes al nmero de
personas (p) y al nmero de experimentos a realizar (n) y calcule la probabilidad de que haya al
menos dos personas con el mismo cumpleaos en un grupo de p personas. Realiza n experimentos
(con semillas desde 0 a n-1) y divide el nmero de experimentos que correspondan a un xito por el
nmero total de experimentos realizados (n), con lo que tendrs la probabilidad buscada. Para
contabilizar los xitos, puede ser til definir primero una funcin que compruebe si hay elementos
repetidos en una lista.
b) Realizando 1000 experimentos, usa la funcin probCumple para calcular las probabilidades de que
haya dos personas con el mismo cumpleaos en grupos de 30, 40, 50 y 60 personas. Te parecen
sorprendentes estas probabilidades? Quizs puedas usar esta informacin para ganar alguna
apuesta.

Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

8

c) Usando la biblioteca Mates.Plot, crea un grfico como el siguiente, que muestra la probabilidad
de de que haya al menos dos personas con el mismo cumpleaos para distintos tamaos del grupo
de personas.


12. Consideremos una variante del problema de la ruina del jugador, en el que el jugador parte de un
capital inicial (c) y quiere obtener un capital objetivo (o) pero realizando como mximo nMax
jugadas. Es decir, el jugador va apostando 1 mientras tiene capital disponible y no ha sobrepasado
el nmero mximo de jugadas. Si en algn momento alcanza el capital objetivo, el juego termina y
el jugador ha ganado. Si se queda sin capital, el juego termina y el jugador ha perdido. Si alcanza el
lmite de jugadas mximo permitido, el juego termina y el jugador obtiene como capital final el que
le quede.
a) Escribe una funcin juego3 que tome como parmetros c, o, nMax y un valor para la semilla (s) y
realice una simulacin del juego, devolviendo una lista con la evolucin del capital del jugador en
dicha simulacin.
b) Usando la biblioteca Mates.Plot, escribe una funcin para generar una grfica de la simulacin en
la que se muestre la evolucin del capital del jugador.
c) Define una funcin para determinar la probabilidad de ganar en esta variante del juego. Adems de
los parmetros c, o, y nMax, esta funcin debe tomar un parmetro que indique el n de
simulaciones a realizar.
d) Define una funcin para determinar la media del capital que tiene el jugador al finalizar el juego
independientemente del motivo de finalizacin. Al igual que en el ejercicio anterior, aade un
parmetro que indique el n de simulaciones a realizar.

13. El problema del coleccionista de cromos.
a) Define una funcin inserta que tome como parmetros un valor y una lista ordenada sin
elementos repetidos (asume esta precondicin), y devuelva la lista ordenada sin elementos
repetidos que se obtiene al insertar (si no est ya presente) el valor en la lista argumento. Por
ejemplo:
inserta 2 [1,3,10] => [1,2,3,10]
inserta 20 [1,3,10] => [1,3,10,20]
Si el valor ya estaba presente en la lista argumento, se devolver la misma lista. Por ejemplo:
inserta 3 [1,3,10] => [1,3,10]

Relacin de Ejercicios 4 Asignatura Informtica. Grado en Matemticas. UMA

9

b) Lee, entiende y comprueba con QuickCheck para listas de enteros la siguiente propiedad para
comprobar la correccin de la funcin inserta:
p_inserta x xs =
estOrdenada xs && distintos xs
==> if x `elem` xs then xs'==xs
else distintos xs'
&& estOrdenada xs'
&& xs' `esPermutacinDe` (x:xs)
where xs' = inserta x xs
donde
distintos :: (Eq a) => [a] -> Bool
distintos [] = True
distintos (x:xs) = all (/=x) xs && distintos xs

estOrdenada :: (Ord a) => [a] -> Bool
estOrdenada xs = and [ x<=y | (x,y) <- zip xs (tail xs) ]

esPermutacinDe :: (Eq a) => [a] -> [a] -> Bool
xs `esPermutacinDe` ys = null (xs \\ ys) && null (ys \\ xs)
c) Supongamos que queremos completar una coleccin con nc cromos distintos y que la probabilidad
de obtener cualquiera de ellos al comprar cromos en un kiosco es la misma. La siguiente funcin
devuelve una lista infinita de cromos aleatoria acorde a estas condiciones:
cromos :: Int -> Semilla -> [Int]
cromos nc s = aleatoriosDe [1..nc] s
de modo que cada cromo distinto queda representado por un nmero entre 1 y nc.
Define una funcin cuentaCromos, con parmetros nc y s, que determine el nmero de cromos
que es necesario comprar para completar una coleccin con nc cromos, si realizamos un
experimento con semilla s. Para ello, se irn contando todos los cromos que son necesarios tomar
de la lista devuelta por cromos nc s hasta completar la coleccin. Puedes representar la coleccin
con un parmetro acumulador (inicialmente la lista vaca), al que debers aadir (usando la funcin
inserta) cromos de la lista aleatoria hasta que la coleccin est completa (hasta que el
acumulador coincida con la lista [1..nc]).
d) Define una funcin promedioCromos que calcule el nmero esperado de cromos necesarios para
completar una coleccin con nc cromos. Para ello, la funcin tomar dos parmetros nc y n,
realizar n experimentos (con distintas semillas desde 0 hasta n-1) para el problema del
coleccionista con nc cromos, calcular el nmero de cromos comprados en cada experimento y
devolver el promedio (media aritmtica) de dichos valores.
e) Supongamos que para el ltimo cromo de la coleccin el fabricante hace una dcima parte de
copias con respecto a los dems cromos. Esto puede ser modelado con la siguiente funcin para
generar cromos bajo estas nuevas condiciones:
cromos' :: Int -> Semilla -> [Int]
cromos' nc s = aleatoriosDe cs s
where cs = nc : concat [ replicate 10 c | c <- [1..nc-1]]
Donde la funcin predefinida replicate n x devuelve una lista con n repeticiones del valor x.
Determina realizando 1000 experimentos el nmero de cromos necesarios para completar una
coleccin de 20 cromos usando estas condiciones y compralo con el caso en el cual hay igual
nmero de copias para cada cromo.

Вам также может понравиться