Diferencia entre revisiones de «Relación 25»
De Informática de 1º de Matemáticas [Curso 2021-22, Grupo 3]
(Página creada con «<source lang='haskell'> -- I1M 2021-22: Relación 25 -- Funciones de entrada/salida: El dilema de Monty Hall -- Departamento de Ciencias de la Computación e Inteligencia A…») |
|||
Línea 55: | Línea 55: | ||
-- 2 | -- 2 | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
escojaPuerta :: IO Int | escojaPuerta :: IO Int | ||
escojaPuerta = | escojaPuerta = do putStrLn "Que puerta elige? " | ||
x <- getLine | |||
if x == "1" || x == "2" || x == "3" | |||
then return (read x :: Int) | |||
else do putStrLn "ERROR: Entrada incorrecta" | |||
escojaPuerta | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 67: | Línea 74: | ||
-- 3 | -- 3 | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
ponPremio :: IO Int | ponPremio :: IO Int | ||
ponPremio = | ponPremio = randomRIO (1::Int,3) | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 88: | Línea 97: | ||
-- 2 (obligada) | -- 2 (obligada) | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
abrePuerta :: Int -> Int -> IO Int | abrePuerta :: Int -> Int -> IO Int | ||
abrePuerta = | abrePuerta c p = if c == p | ||
then do r <- randomRIO (0::Int,1) | |||
return ((filter f [1,2,3])!!r) | |||
else return (head (filter f [1,2,3])) | |||
where f x = x /= c && x /= p | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 105: | Línea 120: | ||
-- 2 | -- 2 | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
otraPuerta :: Int -> Int -> Int | otraPuerta :: Int -> Int -> Int | ||
otraPuerta = | otraPuerta c a = head (filter f [1,2,3]) | ||
where f x = x /= c && x /= a | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 124: | Línea 142: | ||
-- 3 | -- 3 | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
cambiaPuerta :: Int -> Int -> IO Int | cambiaPuerta :: Int -> Int -> IO Int | ||
cambiaPuerta = | cambiaPuerta con cer = do putStr ("Concursante, digame, prefiere mantener su decision original, la puerta "++(show con)++" [mantener] o quiere cambiar a la puerta "++(show cer)++" [cambiar]? ") | ||
x <- getLine | |||
if x == "mantener" | |||
then return con | |||
else if x == "cambiar" | |||
then return cer | |||
else cambiaPuerta con cer | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 147: | Línea 173: | ||
-- ¿Con qué probabilidad nos llevamos el coche si escogemos "cambiar"? | -- ¿Con qué probabilidad nos llevamos el coche si escogemos "cambiar"? | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
concurso :: IO () | concurso :: IO () | ||
concurso = | concurso = do putStrLn "Muy bien, concursante, aqui tiene tres puertas, una de ellas esconde un coche y las otras dos, sendas cabras." | ||
x <- escojaPuerta | |||
y <- ponPremio | |||
w <- abrePuerta x y | |||
putStrLn ("Pues ahora abramos la puerta " ++ show w ++ ":") | |||
putStrLn "Vaya, hay una CABRA!" | |||
z <- cambiaPuerta x (otraPuerta x w) | |||
if z == y | |||
then putStrLn ("Bien, pues abramos la puerta "++show z++": Y hay un COCHE, enhorabuena!") | |||
else putStrLn ("Bien, pues abramos la puerta "++show z++": Y hay una CABRA, lo sentimos mucho!") | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 165: | Línea 203: | ||
-- 5. Devuelva el valor adecuado dependiendo del resultado. | -- 5. Devuelva el valor adecuado dependiendo del resultado. | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
estrategiaMantener :: IO Int | estrategiaMantener :: IO Int | ||
estrategiaMantener = | estrategiaMantener = do p <- ponPremio | ||
c <- randomRIO (1::Int,3) | |||
a <- abrePuerta p c | |||
if p == c | |||
then return 1 | |||
else return 0 | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 183: | Línea 228: | ||
-- 5. Devuelva el valor adecuado dependiendo del resultado. | -- 5. Devuelva el valor adecuado dependiendo del resultado. | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
estrategiaCambiar :: IO Int | estrategiaCambiar :: IO Int | ||
estrategiaCambiar = | estrategiaCambiar = do p <- ponPremio | ||
c <- randomRIO (1::Int,3) | |||
a <- abrePuerta p c | |||
if p == (otraPuerta c a) | |||
then return 1 | |||
else return 0 | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 198: | Línea 250: | ||
-- 68 | -- 68 | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
ejecutaEstrategia :: Int -> IO Int -> IO Int | ejecutaEstrategia :: Int -> IO Int -> IO Int | ||
ejecutaEstrategia = | ejecutaEstrategia n estrategia = ejecutaAux n estrategia 0 | ||
ejecutaAux :: Int -> IO Int -> Int -> IO Int | |||
ejecutaAux n e xs = do y <- e | |||
if n == 0 | |||
then return xs | |||
else ejecutaAux (n-1) e (xs+y) | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Línea 209: | Línea 270: | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- Álvaro Galisteo: | |||
-- 23 personas | |||
</source> | </source> |
Revisión actual del 20:49 4 abr 2022
-- I1M 2021-22: Relación 25
-- Funciones de entrada/salida: El dilema de Monty Hall
-- Departamento de Ciencias de la Computación e Inteligencia Artificial
-- Universidad de Sevilla
-- ============================================================================
-- ============================================================================
-- Librerías auxiliares
-- ============================================================================
import System.Random
import Data.List
import Data.Char
-- ============================================================================
-- Monty Hall es el nombre de un conocido presentador de televisión en
-- Estados Unidos. En uno de sus concursos, se presenta el siguiente dilema:
--
-- El concursante debe elegir una de entre tres puertas cerradas y el premio
-- consiste en llevarse lo que se encuentra detrás de la puerta elegida.
-- Se sabe con certeza que una de las puertas encierra un coche y que las otras
-- dos tienen sendas cabras (se entiende que el concursante prefiere llevarse
-- el coche antes que una cabra).
--
-- Una vez que el concursante haya elegido una puerta, el presentador, que sabe
-- lo que encierra cada puerta, abrirá una de las otras dos, mostrando siempre
-- una cabra.
--
-- A continuación, le da la opción al concursante de cambiar, si lo desea, de
-- puerta o quedarse con su elección original.
--
-- Vamos a plantear un programa interactivo que permita recrear la
-- participación del concursante en el dilema de Monty Hall
-- ============================================================================
-- ----------------------------------------------------------------------------
-- Representación
-- ----------------------------------------------------------------------------
-- Denominaremos a las puertas por los enteros 1, 2 y 3.
-- ----------------------------------------------------------------------------
-- Ejercicio 1. Definir la acción de E/S
-- escojaPuerta :: IO Int
-- que interactúe con el jugador para que decida qué puerta escoger, dando los
-- correspondientes mensajes (se debe devolver un entero entre 1 y 3),
-- por ejemplo:
-- escojaPuerta =>
-- Que puerta elige? c
-- ERROR: Entrada incorrecta
-- Que puerta elige? 4
-- ERROR: Entrada incorrecta
-- Que puerta elige? 2
-- 2
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
escojaPuerta :: IO Int
escojaPuerta = do putStrLn "Que puerta elige? "
x <- getLine
if x == "1" || x == "2" || x == "3"
then return (read x :: Int)
else do putStrLn "ERROR: Entrada incorrecta"
escojaPuerta
-- ----------------------------------------------------------------------------
-- Ejercicio 2. Definir la acción
-- ponPremio :: IO Int
-- tal que devuelva la puerta que contiene el premio del concurso.
-- Para ello se debe seleccionar de forma aleatoria un valor entero entre 1 y 3:
-- ponPremio =>
-- 3
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
ponPremio :: IO Int
ponPremio = randomRIO (1::Int,3)
-- ----------------------------------------------------------------------------
-- Ejercicio 3. Definir la función
-- abrePuerta :: Int -> Int -> IO Int
-- tal que (abrePuerta concursante premio) devuelve el número de una puerta que
-- abre el presentador. La puerta devuelta nunca puede ser la que contiene el
-- premio ni la que ha escogido el concursante, y, en caso de que el jugador
-- haya elegido la puerta con premio, se debe escoger aleatoriamente entre las
-- otras dos.
-- abrePuerta 1 1 =>
-- 2 (pero podía haber sido la 3)
-- abrePuerta 1 1 =>
-- 3 (pero podía haber sido la 2)
-- abrePuerta 1 2 =>
-- 3 (obligada)
-- abrePuerta 1 3 =>
-- 2 (obligada)
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
abrePuerta :: Int -> Int -> IO Int
abrePuerta c p = if c == p
then do r <- randomRIO (0::Int,1)
return ((filter f [1,2,3])!!r)
else return (head (filter f [1,2,3]))
where f x = x /= c && x /= p
-- ----------------------------------------------------------------------------
-- Ejercicio 4. Definir la acción
-- otraPuerta :: Int -> Int -> Int
-- tal que (otraPuerta concursante abierta) devuelve el número de la puerta que
-- no es igual a la del concursante ni a la que ya está abierta (se supone
-- que "concursante" es distinto de "abierta").
-- otraPuerta 1 2 =>
-- 3
-- otraPuerta 2 1 =>
-- 3
-- otraPuerta 3 1 =>
-- 2
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
otraPuerta :: Int -> Int -> Int
otraPuerta c a = head (filter f [1,2,3])
where f x = x /= c && x /= a
-- ----------------------------------------------------------------------------
-- Ejercicio 5. Definir la acción
-- cambiaPuerta :: Int -> Int -> IO Int
-- tal que (cambiaPuerta concursante cerrada) devuelve el número de la puerta
-- que el concursante al final termina escogiendo después de haberle dado a
-- elegir entre "mantener" la elección original "concursante" o "cambiar" a
-- la "cerrada".
-- cambiaPuerta 1 3 =>
-- Concursante, digame, prefiere mantener su decision original, la puerta 1 [mantener]
-- o quiere cambiar a la puerta 3 [cambiar]? mantener
-- 1
-- Concursante, digame, prefiere mantener su decision original, la puerta 1 [mantener]
-- o quiere cambiar a la puerta 3 [cambiar]? cambiar
-- 3
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
cambiaPuerta :: Int -> Int -> IO Int
cambiaPuerta con cer = do putStr ("Concursante, digame, prefiere mantener su decision original, la puerta "++(show con)++" [mantener] o quiere cambiar a la puerta "++(show cer)++" [cambiar]? ")
x <- getLine
if x == "mantener"
then return con
else if x == "cambiar"
then return cer
else cambiaPuerta con cer
-- ----------------------------------------------------------------------------
-- Ejercicio 6. Definir la acción
-- concurso :: IO ()
-- tal que se describa una ronda completa del concurso de Monty Hall.
-- concurso =>
-- Muy bien, concursante, aqui tiene tres puertas, una de ellas esconde un
-- coche y las otras dos, sendas cabras.
-- Que puerta elige? 1
-- Pues ahora abramos la puerta 2:
-- Vaya, hay una CABRA!
-- Concursante, digame, prefiere mantener su decision original, la puerta 1 [mantener]
-- o quiere cambiar a la puerta 3 [cambiar]? mantener
-- Bien, pues abramos la puerta 1: Y hay un COCHE, enhorabuena!
-- ó
-- Bien, pues abramos la puerta 1: Y hay una CABRA, lo sentimos mucho!
-- Juegue varias veces. ¿Qué estrategia es mejor, mantener o cambiar?
-- ¿Con qué probabilidad nos llevamos el coche si escogemos "mantener"?
-- ¿Con qué probabilidad nos llevamos el coche si escogemos "cambiar"?
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
concurso :: IO ()
concurso = do putStrLn "Muy bien, concursante, aqui tiene tres puertas, una de ellas esconde un coche y las otras dos, sendas cabras."
x <- escojaPuerta
y <- ponPremio
w <- abrePuerta x y
putStrLn ("Pues ahora abramos la puerta " ++ show w ++ ":")
putStrLn "Vaya, hay una CABRA!"
z <- cambiaPuerta x (otraPuerta x w)
if z == y
then putStrLn ("Bien, pues abramos la puerta "++show z++": Y hay un COCHE, enhorabuena!")
else putStrLn ("Bien, pues abramos la puerta "++show z++": Y hay una CABRA, lo sentimos mucho!")
-- ----------------------------------------------------------------------------
-- Ejercicio 7. Definir la acción
-- estrategiaMantener :: IO Int
-- tal que devuelva un 1 si en una ronda del concurso, el jugador se llevó
-- el premio o 0 en caso contrario. Suponga que el jugador siempre escoge
-- mantener su decisión original.
--
-- Para ello:
-- 1. Seleccione de forma aleatoria una puerta para el premio.
-- 2. Seleccione de forma aleatoria una puerta para el concursante.
-- 3. Abra una de las puertas que contiene un cabra sin que sea la del concursante.
-- 4. Mantenga la decisión del concursante.
-- 5. Devuelva el valor adecuado dependiendo del resultado.
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
estrategiaMantener :: IO Int
estrategiaMantener = do p <- ponPremio
c <- randomRIO (1::Int,3)
a <- abrePuerta p c
if p == c
then return 1
else return 0
-- ----------------------------------------------------------------------------
-- Ejercicio 8. Definir la acción
-- estrategiaCambiar :: IO Int
-- tal que devuelva un 1 si en una ronda del concurso, el jugador se llevó
-- el premio o 0 en caso contrario. Suponga que el jugador siempre escoge
-- cambiar su decisión original.
--
-- Para ello:
-- 1. Seleccione de forma aleatoria una puerta para el premio.
-- 2. Seleccione de forma aleatoria una puerta para el concursante.
-- 3. Abra una de las puertas que contiene un cabra sin que sea la del concursante.
-- 4. Cambie la decisión del concursante a la puerta que queda sin abrir.
-- 5. Devuelva el valor adecuado dependiendo del resultado.
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
estrategiaCambiar :: IO Int
estrategiaCambiar = do p <- ponPremio
c <- randomRIO (1::Int,3)
a <- abrePuerta p c
if p == (otraPuerta c a)
then return 1
else return 0
-- ----------------------------------------------------------------------------
-- Ejercicio 9. Definir la acción
-- ejecutaEstrategia :: Int -> IO Int -> IO Int
-- tal que (ejecutaEstrategia n estrategia) ejecuta de forma consecutiva n veces
-- la estrategia pasada como segundo argumento. Devuelve el número de veces que
-- el concursante se llevó el premio. Por ejemplo:
-- ejecuta 100 estrategiaMantener =>
-- 30
-- ejecuta 100 estrategiaCambiar =>
-- 68
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
ejecutaEstrategia :: Int -> IO Int -> IO Int
ejecutaEstrategia n estrategia = ejecutaAux n estrategia 0
ejecutaAux :: Int -> IO Int -> Int -> IO Int
ejecutaAux n e xs = do y <- e
if n == 0
then return xs
else ejecutaAux (n-1) e (xs+y)
-- ----------------------------------------------------------------------------
-- Ejercicio 10.
-- ¿Cuál es número mínimo de personas que debe haber en una fiesta para
-- tener una probabilidad del 50% de que al menos dos de ellas tengan el mismo
-- cumpleaños?
-- ----------------------------------------------------------------------------
-- Álvaro Galisteo:
-- 23 personas