{"id":7699,"date":"2022-04-07T16:44:09","date_gmt":"2022-04-07T14:44:09","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=7699"},"modified":"2022-04-07T16:44:09","modified_gmt":"2022-04-07T14:44:09","slug":"pfh-ejercicios-con-acciones-io-entrada-salida","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/pfh-ejercicios-con-acciones-io-entrada-salida\/","title":{"rendered":"PFH: Ejercicios con acciones IO (entrada\/salida)"},"content":{"rendered":"<p>He a\u00f1adido a la colecci\u00f3n de <a href=\"https:\/\/bit.ly\/3CeabJd\">Ejercicios de programaci\u00f3n funcional con Haskell<\/a> la relaci\u00f3n de <a href=\"https:\/\/bit.ly\/3DXo5jK\">Ejercicios con acciones IO (entrada\/salida)<\/a> en la que se practica con las acciones IO (de entrada\/salida) estudiadas en el <a href=\"https:\/\/jaalonso.github.io\/materias\/PFconHaskell\/temas\/tema-13.html\">tema 13<\/a>. Concretamente, funciones para leer y escribir desde los dispositivos est\u00e1ndar y desde ficheros, as\u00ed como funciones con n\u00fameros aleatorios.<\/p>\n<p>El contenido de la relaci\u00f3n es el siguiente<\/p>\n<p><!-- pre --><\/p>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- \u00a7 Librer\u00edas auxiliares                                             --\n-- ---------------------------------------------------------------------\n\nimport Prelude\nimport Control.Monad (liftM2)\nimport System.Random (randomRIO)\nimport Text.Read     (readMaybe)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 1.1. Definir la funci\u00f3n\n--    leeEntero1 :: String -> Int\n-- tal que (leeEntero1 cs) es el entero correspondiente a la cadena\n-- cs. Por ejemplo,\n--    \u03bb> leeEntero1 \"325\"\n--    325\n--    \u03bb> leeEntero1 \"-25\"\n--    -25\n--    \u03bb> leeEntero1 \"3.25\"\n--    *** Exception: Prelude.read: no parse\n-- ---------------------------------------------------------------------\n\nleeEntero1 :: String -> Int\nleeEntero1 = read\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 1.2. Definir la funci\u00f3n\n--    leeEntero :: String -> Maybe Int\n-- tal que (leeEntero1 cs) es justo el entero correspondiente a la\n-- cadena cs, si representa un entero y Nothing en caso contrario. Por\n-- ejemplo,\n--    \u03bb> leeEntero \"325\"\n--    Just 325\n--    \u03bb> leeEntero \"-25\"\n--    Just (-25)\n--    \u03bb> leeEntero \"3.25\"\n--    Nothing\n-- ---------------------------------------------------------------------\n\nleeEntero :: String -> Maybe Int\nleeEntero = readMaybe\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 1.3. Definir la funci\u00f3n\n--    leeLinea :: Read a => IO (Maybe a)\n-- que lee una l\u00ednea y devuelve el t\u00e9rmino del tipo indicado, si lo es o\n-- Nothing en caso contrario. Por ejemplo,\n--    \u03bb> leeLinea :: IO (Maybe Int)\n--    325\n--    Just 325\n--    \u03bb> leeLinea :: IO (Maybe Int)\n--    3.25\n--    Nothing\n--    \u03bb> leeLinea :: IO (Maybe Float)\n--    3.25\n--    Just 3.25\n-- ---------------------------------------------------------------------\n\nleeLinea :: Read a => IO (Maybe a)\nleeLinea = fmap readMaybe getLine\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2.1. Definir la funci\u00f3n\n--    sumaDosNumeros :: IO ()\n-- que lea dos n\u00fameros y devuelva su suma. Por ejemplo,\n--    \u03bb> sumaDosNumeros\n--    Escribe el primer numero:\n--    2\n--    Escribe el segundo numero:\n--    3\n--    La suma de los dos numeros es 5.\n-- ---------------------------------------------------------------------\n\nsumaDosNumeros :: IO ()\nsumaDosNumeros = do\n  putStrLn \"Escribe el primer numero:\"\n  x <- readLn\n  putStrLn \"Escribe el segundo numero:\"\n  y <- readLn\n  putStrLn $ \"La suma de los dos numeros es \" ++ show (x + y :: Int) ++ \".\"\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2.2. Definir la funci\u00f3n\n--    replicateM :: Int -> IO a -> IO [a]\n-- tal que (replicateM n a) repite n veces la acci\u00f3n a. Por ejemplo,\n--    \u03bb> replicateM 2 (leeLinea :: IO (Maybe Int))\n--    325\n--    3.25\n--    [Just 325,Nothing]\n-- ---------------------------------------------------------------------\n\nreplicateM :: Int -> IO a -> IO [a]\nreplicateM n a\n  | n <= 0    = return []\n  | otherwise = do\n      x  <- a\n      xs <- replicateM (n - 1) a\n      return (x : xs)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2.3. Definir la acci\u00f3n\n--    sumaVarios :: IO ()\n-- que pregunte por la cantidad de n\u00fameros a sumar, los leas e imprima\n-- el resultado de su suma. Por ejemplo,\n--    \u03bb> sumaVarios\n--    Escribe la cantidad de numeros a sumar\n--    3\n--    Escribe el siguiente numero:\n--    2\n--    Escribe el siguiente numero:\n--    4\n--    Escribe el siguiente numero:\n--    5\n--    La suma de todos los numeros es 11.\n-- ---------------------------------------------------------------------\n\nsumaVarios :: IO ()\nsumaVarios = do\n  putStrLn \"Escribe la cantidad de numeros a sumar\"\n  n  <- readLn\n  xs <- replicateM n (putStrLn \"Escribe el siguiente numero:\" >> readLn) :: IO [Int]\n  putStrLn (\"La suma de todos los numeros es \" ++ show (sum xs) ++ \".\")\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 2.4. Definir la acci\u00f3n\n--    sumaVarios' :: IO ()\n-- que es una variante de la anterior pero indica el progreso de los\n-- n\u00fameros. Por ejemplo,\n--    \u03bb> sumaVarios'\n--    Escribe la cantidad de numeros a sumar\n--    3\n--    Escribe el n\u00famero 1 de 3:\n--    2\n--    Escribe el n\u00famero 2 de 3:\n--    4\n--    Escribe el n\u00famero 3 de 3:\n--    5\n--    La suma de todos los numeros es 11.\n-- ---------------------------------------------------------------------\n\nsumaVarios' :: IO ()\nsumaVarios' = do\n  putStrLn \"Escribe la cantidad de numeros a sumar\"\n  n  <- readLn\n  xs <- mapM (\\i -> putStrLn (\"Escribe el n\u00famero \" ++ show i ++ \" de \" ++ show n ++ \":\") >> readLn)\n             [1 .. n :: Int] :: IO [Int]\n  putStrLn (\"La suma de todos los numeros es \" ++ show (sum xs) ++ \".\")\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 3. Definir el procedimiento\n--    wc :: FilePath -> IO (Int, Int, Int)\n-- tal que (wc f) lle el contenido del fichero f y devuelve una terna\n-- formada por sus n\u00fameros de filas, palabras y caracteres. Por ejemplo,\n-- si el contenido del fichero \/tmp\/ejemplo1.txt es\n--    Esta es la primera fila\n--    esta es la segunda\n--    y esta es la \u00faltima.\n-- entonces\n--    \u03bb> wc \"\/tmp\/ejemplo1.txt\"\n--    (3,14,64)\n-- ---------------------------------------------------------------------\n\nwc :: FilePath -> IO (Int, Int, Int)\nwc f = do\n  s <- readFile f\n  return (length (lines s), length (words s), length s)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 4. Definir el procedimiento\n--    dosDados :: IO (Int, Int)\n-- que devuelva un par de n\u00fameros aleatorios que representan los valores\n-- de dos dados. Por ejemplo,\n--    \u03bb> dosDados\n--    (1,2)\n--    \u03bb> dosDados\n--    (4,5)\n-- ---------------------------------------------------------------------\n\ndosDados :: IO (Int, Int)\ndosDados = liftM2 (,) dado dado\n  where\n    dado = randomRIO (1, 6)\n\n-- 2\u00aa definici\u00f3n\ndosDados2 :: IO (Int, Int)\ndosDados2 = (,) <$> dado <*> dado\n  where\n    dado = randomRIO (1, 6)\n\n-- 3\u00aa definici\u00f3n\ndosDados3 :: IO (Int, Int)\ndosDados3 = do\n  d1 <- randomRIO (1, 6)\n  d2 <- randomRIO (1, 6)\n  return (d1, d2)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 5.1. Una expresi\u00f3n de la forma\n--    2d8 + 4\n-- se interpreta como lanzar dos dos de 8 cara y sumarle 4. Se puede\n-- representar mediante la expresi\u00f3n\n--    2 `D` 8 `Mas` Const 4\n-- usando el tipo datos ExpDado definido por\n--    data ExpDado = D Int Int\n--                 | Const Int\n--                 | Mas ExpDado ExpDado\n--      deriving (Show, Eq)\n-- y declarando los siguientes operadores infijos\n--    infix  7 `D`\n--    infixl 6 `Mas`\n--\n-- Definir el procedimiento\n--    valor :: ExpDado -> IO Int\n-- tal que (valor e) devuelve el valor de la expresi\u00f3n e. Por\n-- ejemplo,\n--    \u03bb> valor (2 `D` 8 `Mas` Const 4)\n--    8\n--    \u03bb> valor (2 `D` 8 `Mas` Const 4)\n--    14\n--    \u03bb> valor (3 `D` 6)\n--    10\n--    \u03bb> valor (2 `D` 6 `Mas` 1 `D` 8)\n--    15\n--    \u03bb> valor (2 `D` 6 `Mas` 1 `D` 8)\n--    18\n-- ---------------------------------------------------------------------\n\n\ndata ExpDado = D Int Int\n             | Const Int\n             | Mas ExpDado ExpDado\n  deriving (Show, Eq)\n\ninfix  7 `D`\ninfixl 6 `Mas`\n\nvalor :: ExpDado -> IO Int\nvalor (D c d)\n  | c <= 0    = return 0\n  | d <= 0    = return 0\n  | otherwise = sum <$> replicateM c (randomRIO (1, d))\nvalor (Const i) = return i\nvalor (Mas x y) = (+) <$> valor x <*> valor y\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 5.2. Definir la funci\u00f3n\n--    rango :: ExpDado -> (Int, Int)\n-- tal que (rango e) es el par formado por el m\u00ednimo y m\u00e1ximo de los\n-- posibles valores de la expresi\u00f3n e. Por ejemplo,\n--    \u03bb> rango (2 `D` 6 `Mas` 1 `D` 8)\n--    (3,20)\n-- ---------------------------------------------------------------------\n\nrango :: ExpDado -> (Int, Int)\nrango (D c d)\n  | c <= 0    = (0, 0)\n  | d <= 0    = (0, 0)\n  | otherwise = (c, c * d)\nrango (Const i) = (i, i)\nrango (Mas x y) = (l1 + l2, u1 + u2)\n  where (l1, u1) = rango x\n        (l2, u2) = rango y\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 6.1. La baraja inglesa consta de 4 palos (picas, corazones,\n-- rombos y tr\u00e9boles) y cada palo est\u00e1 formado por 13 cartas (A ,2, 3,\n-- 4, 5, 6, 7, 8, 9, 10, J, Q y K).\n--\n-- La baraja se puede representar mediante los siguientes tipos de\n-- datos:\n--    data Palo = Picas | Corazones | Rombos | Treboles\n--      deriving (Show, Eq, Bounded, Enum)\n--\n--    data NumeroCarta = A | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | C10 | J | Q | K\n--      deriving (Show, Eq, Bounded, Enum)\n--\n--    data Carta = Carta NumeroCarta Palo\n--      deriving (Show, Eq)\n--\n-- Definir la lista\n--    cartas :: [Carta]\n-- cuyos elementos son todas las cartas. Por ejemplo,\n--    \u03bb> take 26 cartas\n--    [Carta A  Picas,Carta A  Corazones,Carta A  Rombos,Carta A  Treboles,\n--     Carta C2 Picas,Carta C2 Corazones,Carta C2 Rombos,Carta C2 Treboles,\n--     Carta C3 Picas,Carta C3 Corazones,Carta C3 Rombos,Carta C3 Treboles]\n-- ---------------------------------------------------------------------\n\ndata Palo = Picas | Corazones | Rombos | Treboles\n  deriving (Show, Eq, Bounded, Enum)\n\ndata NumeroCarta = A | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | C10 | J | Q | K\n  deriving (Show, Eq, Bounded, Enum)\n\ndata Carta = Carta NumeroCarta Palo\n  deriving (Show, Eq)\n\ncartas :: [Carta]\ncartas = [Carta n p | n <- [minBound ..], p <- [minBound ..]]\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 6.2. Definir la funci\u00f3n\n--    extrae :: Int -> [a] -> (a, [a])\n-- tal que (extrae i xs) es el par formado por el elemento i-\u00e9simo de xs\n-- y los restantes elementos. Por ejemplo,\n--    \u03bb> extrae 1 [3,5,4]\n--    (5,[3,4])\n--    \u03bb> extrae 7 [3,5,4]\n--    (*** Exception: indice fuera de ranfo\n-- ---------------------------------------------------------------------\n\nextrae :: Int -> [a] -> (a, [a])\nextrae _ []       = error \"indice fuera de ranfo\"\nextrae 0 (x : xs) = (x, xs)\nextrae i (x : xs) = (y, x : ys)\n  where (y, ys) = extrae (i - 1) xs\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 6.3. Definir la funci\u00f3n\n--    permutacion :: [a] -> IO [a]\n-- tal que (permutacion xs) es una permutaci\u00f3n aleatoria de xs. Por\n-- ejemplo,\n--    \u03bb> permutacion [1..6]\n--    [5,4,3,1,6,2]\n--    \u03bb> permutacion [1..6]\n--    [3,4,6,2,1,5]\n-- ---------------------------------------------------------------------\n\npermutacion :: [a] -> IO [a]\npermutacion [] = return []\npermutacion xs = do\n  i <- randomRIO (0, length xs - 1)\n  let (y, ys) = extrae i xs\n  zs <- permutacion ys\n  return (y : zs)\n\n-- ---------------------------------------------------------------------\n-- Ejercicio 6.4. Definir el procedimiento\n--    cartasBarajadas :: Int -> IO [Carta]\n-- tal que (cartasBarajadas n) que baraja las cartas y devuelve la lista\n-- formada por las n primeras de ellas. Por ejemplo,\n--    \u03bb> cartasBarajadas 3\n--    [Carta C3 Treboles,Carta C7 Picas,Carta C6 Treboles]\n--    \u03bb> cartasBarajadas 3\n--    [Carta C10 Corazones,Carta C10 Treboles,Carta A Corazones]\n--    \u03bb> cartasBarajadas 3\n--    [Carta C3 Rombos,Carta C2 Rombos,Carta Q Corazones]\n-- ---------------------------------------------------------------------\n\n-- 1\u00aa soluci\u00f3n\ncartasBarajadas :: Int -> IO [Carta]\ncartasBarajadas n = do\n  cs <- permutacion cartas\n  return (take n cs)\n\n-- 2\u00aa soluci\u00f3n\ncartasBarajadas2 :: Int -> IO [Carta]\ncartasBarajadas2 n =\n  take n <$> permutacion cartas\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>He a\u00f1adido a la colecci\u00f3n de Ejercicios de programaci\u00f3n funcional con Haskell la relaci\u00f3n de Ejercicios con acciones IO (entrada\/salida) en la que se practica con las acciones IO (de entrada\/salida) estudiadas en el tema 13. Concretamente, funciones para leer y escribir desde los dispositivos est\u00e1ndar y desde ficheros, as\u00ed como funciones con n\u00fameros aleatorios&#8230;.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[337],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7699"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/comments?post=7699"}],"version-history":[{"count":1,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7699\/revisions"}],"predecessor-version":[{"id":7700,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/7699\/revisions\/7700"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=7699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=7699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=7699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}