{"id":1677,"date":"2011-11-09T18:46:08","date_gmt":"2011-11-09T18:46:08","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/i1m2011-ejercicios-de-definiciones-por-comprension-y-cifrado-cesar-en-haskell\/"},"modified":"2013-03-08T05:49:00","modified_gmt":"2013-03-08T05:49:00","slug":"i1m2011-ejercicios-de-definiciones-por-comprension-y-cifrado-cesar-en-haskell","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/i1m2011-ejercicios-de-definiciones-por-comprension-y-cifrado-cesar-en-haskell\/","title":{"rendered":"I1M2011: Ejercicios de definiciones por comprensi\u00f3n y cifrado C\u00e9sar en Haskell"},"content":{"rendered":"<p>En la clase de hoy de <a href=\"http:\/\/www.cs.us.es\/~jalonso\/cursos\/i1m-11\">Inform\u00e1tica de 1\u00ba del Grado en Matem\u00e1ticas<\/a> hemos comentado las soluciones a los 5 \u00faltimos ejercicios de la <a href=\"https:\/\/www.glc.us.es\/~jalonso\/ejerciciosI1M2011G1\/images\/0\/0a\/Rel_4.hs\">4\u00aa relaci\u00f3n<\/a>, que tratan sobre definiciones por comprensi\u00f3n, y los de la <a href=\"https:\/\/www.glc.us.es\/~jalonso\/ejerciciosI1M2011G1\/images\/0\/0a\/Rel_5.hs\">5\u00aa relaci\u00f3n<\/a>, que ampl\u00eda la codificaci\u00f3n C\u00e9sar vista en clase para incluir las may\u00fasculas.<\/p>\n<p>Los ejercicios, y sus soluciones, se muestran a continuaci\u00f3n: Los de la 4\u00aa relaci\u00f3n son<br \/>\n<!--more--><\/p>\n<pre lang=\"haskell\">\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 6. Definir, por comprensi\u00f3n, la funci\u00f3n\r\n--    sumaConsecutivos :: [Int] -> [Int]\r\n-- tal que (sumaConsecutivos xs) es la suma de los pares de elementos\r\n-- consecutivos de la lista xs. Por ejemplo,\r\n--    sumaConsecutivos [3,1,5,2]  ==  [4,6,7]\r\n--    sumaConsecutivos [3]        ==  []\r\n-- ---------------------------------------------------------------------\r\n\r\nsumaConsecutivos :: [Int] -> [Int]\r\nsumaConsecutivos xs = [x+y | (x,y) <- zip xs (tail xs)]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 7.  La distancia de Hamming entre dos listas es el n\u00famero\r\n-- de posiciones en que los correspondientes elementos son\r\n-- distintos. Por ejemplo, la distancia de Hamming entre \"roma\" y \"loba\" \r\n-- es 2 (porque hay 2 posiciones en las que los elementos\r\n-- correspondientes son distintos: la 1\u00aa y la 3\u00aa). \r\n--    \r\n-- Definir la funci\u00f3n\r\n--    distancia :: Eq a => [a] -> [a] -> Int\r\n-- tal que (distancia xs ys) es la distancia de Hamming entre xs e\r\n-- ys. Por ejemplo,\r\n--    distancia \"romano\" \"comino\"  ==  2\r\n--    distancia \"romano\" \"camino\"  ==  3\r\n--    distancia \"roma\"   \"comino\"  ==  2\r\n--    distancia \"roma\"   \"camino\"  ==  3\r\n--    distancia \"romano\" \"ron\"     ==  1\r\n--    distancia \"romano\" \"cama\"    ==  2\r\n--    distancia \"romano\" \"rama\"    ==  1\r\n-- ---------------------------------------------------------------------\r\n\r\ndistancia :: Eq a => [a] -> [a] -> Int\r\ndistancia xs ys = sum [1 | (x,y) <- zip xs ys, x \/= y] \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 8. La suma de la serie\r\n--    1\/1^2 + 1\/2^2 + 1\/3^2 + 1\/4^2 + ...\r\n-- es pi^2\/6. Por tanto, pi se puede aproximar mediante la ra\u00edz cuadrada\r\n-- de 6 por la suma de la serie.\r\n-- \r\n-- Definir la funci\u00f3n aproximaPi tal que (aproximaPi n) es la aproximaci\u00f3n \r\n-- de pi obtenida mediante n t\u00e9rminos de la serie. Por ejemplo, \r\n--    aproximaPi 4    == sqrt(6*(1\/1^2 + 1\/2^2 + 1\/3^2 + 1\/4^2))\r\n--                    == 2.9226129861250305\r\n--    aproximaPi 1000 == 3.1406380562059946\r\n-- ---------------------------------------------------------------------\r\n\r\naproximaPi n = sqrt(6*sum [1\/x^2 | x <- [1..n]])\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 9. Un n\u00famero natural n se denomina abundante si es menor\r\n-- que la suma de sus divisores propios. Por ejemplo, 12 y 30 son\r\n-- abundantes pero 5 y 28 no lo son.\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 9.1. Definir la funci\u00f3n numeroAbundante tal que\r\n-- (numeroAbundante n) se verifica si n es un n\u00famero abundante. Por\r\n-- ejemplo, \r\n--    numeroAbundante 5  == False\r\n--    numeroAbundante 12 == True\r\n--    numeroAbundante 28 == False\r\n--    numeroAbundante 30 == True\r\n-- ---------------------------------------------------------------------\r\n\r\ndivisores:: Int -> [Int]\r\ndivisores n = [m | m <- [1..n-1], n `mod` m == 0]\r\n\r\nnumeroAbundante:: Int -> Bool \r\nnumeroAbundante n = n < sum (divisores n)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 9.2. Definir la funci\u00f3n numerosAbundantesMenores tal que\r\n-- (numerosAbundantesMenores n) es la lista de n\u00fameros abundantes\r\n-- menores o iguales que n. Por ejemplo,\r\n--    numerosAbundantesMenores 50  ==  [12,18,20,24,30,36,40,42,48]\r\n-- ---------------------------------------------------------------------\r\n\r\nnumerosAbundantesMenores :: Int -> [Int]\r\nnumerosAbundantesMenores n = [x | x <- [1..n], numeroAbundante x]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 9.3. Definir la funci\u00f3n todosPares tal que (todosPares n)\r\n-- se verifica si todos los n\u00fameros abundantes menores o iguales que n\r\n-- son pares. Por ejemplo,\r\n--    todosPares 10    ==  True\r\n--    todosPares 100   ==  True\r\n--    todosPares 1000  ==  False\r\n-- ---------------------------------------------------------------------\r\n\r\ntodosPares :: Int -> Bool\r\ntodosPares n = and [even x | x <- numerosAbundantesMenores n]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 9.4. Definir la constante primerAbundanteImpar que calcule\r\n-- el primer n\u00famero natural abundante impar. Determinar el valor de\r\n-- dicho n\u00famero.\r\n-- ---------------------------------------------------------------------\r\n\r\nprimerAbundanteImpar:: Int\r\nprimerAbundanteImpar = head [x | x <-[1..], numeroAbundante x, odd x]\r\n\r\n-- Su c\u00e1lculo es\r\n--    ghci> primerAbundanteImpar\r\n--    945\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 10.1. (Problema 9 del Proyecto Euler). Una terna pitag\u00f3rica\r\n-- es una terna de n\u00fameros naturales (a,b,c) tal que a<b<c y\r\n-- a^2+b^2=c^2. Por ejemplo (3,4,5) es una terna pitag\u00f3rica. \r\n-- \r\n-- Definir la funci\u00f3n \r\n--    ternasPitagoricas :: Integer -> [[Integer]]\r\n-- tal que (ternasPitagoricas x) es la lista de las ternas pitag\u00f3ricas\r\n-- cuya suma es x. Por ejemplo,\r\n--    ternasPitagoricas 12  ==  [(3,4,5)]\r\n--    ternasPitagoricas 60  ==  [(10,24,26),(15,20,25)]\r\n-- ---------------------------------------------------------------------\r\n\r\nternasPitagoricas :: Integer -> [(Integer,Integer,Integer)]\r\nternasPitagoricas x = [(a,b,c) | a <- [1..x], \r\n                                 b <- [a+1..x], \r\n                                 c <- [x-a-b], \r\n                                 a^2 + b^2 == c^2]\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 10.2. Definir la constante euler9 tal que euler9 es producto\r\n-- abc donde (a,b,c) es la \u00fanica terna pitag\u00f3rica tal que a+b+c=1000. \r\n-- Calcular el valor de euler9.\r\n-- ---------------------------------------------------------------------\r\n\r\neuler9 = a*b*c\r\n    where (a,b,c) = head (ternasPitagoricas 1000)\r\n\r\n-- El c\u00e1lculo del valor de euler9 es\r\n--    ghci> euler9\r\n--    31875000\r\n<\/pre>\n<p>Los de la 5\u00aa relaci\u00f3n son<\/p>\n<pre lang=\"haskell\">\r\n-- I1M 2011-12: Rel_5_sol.hs (5 de Noviembre de 2011)\r\n-- Definiciones por comprensi\u00f3n: El cifrado C\u00e9sar.\r\n-- Departamento de Ciencias de la Computaci\u00f3n e I.A.\r\n-- Universidad de Sevilla\r\n-- =====================================================================\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Introducci\u00f3n                                                       --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- En el tema 5, cuyas transparencias se encuentran en \r\n--    http:\/\/www.cs.us.es\/~jalonso\/cursos\/i1m-11\/temas\/tema-5.pdf\r\n-- se estudi\u00f3, como aplicaci\u00f3n de las definiciones por comprennsi\u00f3n, el\r\n-- cifrado C\u00e9sar. El objetivo de esta relaci\u00f3n es modificar el programa\r\n-- de cifrado C\u00e9sar para que pueda utilizar tambi\u00e9n letras\r\n-- may\u00fasculas. Por ejemplo,  \r\n--    *Main> descifra \"Ytit Ufwf Sfif\"\r\n--    \"Todo Para Nada\"\r\n-- Para ello, se propone la modificaci\u00f3n de las funciones\r\n-- correspondientes del tema 5.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Importaci\u00f3n de librer\u00edas auxiliares                                --\r\n-- ---------------------------------------------------------------------\r\n\r\nimport Data.Char\r\n\r\n-- (minuscula2int c) es el entero correspondiente a la letra min\u00fascula\r\n-- c. Por ejemplo, \r\n--    minuscula2int 'a'  ==  0\r\n--    minuscula2int 'd'  ==  3\r\n--    minuscula2int 'z'  ==  25\r\nminuscula2int :: Char -> Int\r\nminuscula2int c = ord c - ord 'a'\r\n\r\n-- (mayuscula2int c) es el entero correspondiente a la letra may\u00fascula\r\n-- c. Por ejemplo, \r\n--    mayuscula2int 'A'  ==  0\r\n--    mayuscula2int 'D'  ==  3\r\n--    mayuscula2int 'Z'  ==  25\r\nmayuscula2int :: Char -> Int\r\nmayuscula2int c = ord c - ord 'A'\r\n\r\n-- (int2minuscula n) es la letra min\u00fascula correspondiente al entero\r\n-- n. Por ejemplo, \r\n--    int2minuscula 0   ==  'a'\r\n--    int2minuscula 3   ==  'd'\r\n--    int2minuscula 25  ==  'z'\r\nint2minuscula :: Int -> Char\r\nint2minuscula n = chr (ord 'a' + n)\r\n\r\n-- (int2mayuscula n) es la letra min\u00fascula correspondiente al entero\r\n-- n. Por ejemplo, \r\n--    int2mayuscula 0   ==  'A'\r\n--    int2mayuscula 3   ==  'D'\r\n--    int2mayuscula 25  ==  'Z'\r\nint2mayuscula :: Int -> Char\r\nint2mayuscula n = chr (ord 'A' + n)\r\n\r\n-- (desplaza n c) es el car\u00e1cter obtenido desplazando n caracteres el\r\n-- car\u00e1cter c. Por ejemplo, \r\n--    desplaza   3  'a'  ==  'd'\r\n--    desplaza   3  'y'  ==  'b'\r\n--    desplaza (-3) 'd'  ==  'a'\r\n--    desplaza (-3) 'b'  ==  'y'\r\n--    desplaza   3  'A'  ==  'D'\r\n--    desplaza   3  'Y'  ==  'B'\r\n--    desplaza (-3) 'D'  ==  'A'\r\n--    desplaza (-3) 'B'  ==  'Y'\r\ndesplaza :: Int -> Char -> Char\r\ndesplaza n c \r\n    | elem c ['a'..'z'] = int2minuscula ((minuscula2int c+n) `mod` 26)\r\n    | elem c ['A'..'Z'] = int2mayuscula ((mayuscula2int c+n) `mod` 26)\r\n    | otherwise         = c\r\n\r\n-- (codifica n xs) es el resultado de codificar el texto xs con un\r\n-- desplazamiento n. Por ejemplo, \r\n--    *Main> codifica   3  \"En Todo La Medida\" \r\n--    \"Hq Wrgr Od Phglgd\"\r\n--    *Main> codifica (-3) \"Hq Wrgr Od Phglgd\"\r\n--    \"En Todo La Medida\"\r\ncodifica :: Int -> String -> String\r\ncodifica n xs = [desplaza n x | x <- xs]\r\n\r\n-- tabla es la lista de la frecuencias de las letras en castellano, Por\r\n-- ejemplo, la frecuencia de la 'a' es del 12.53%, la de la 'b' es\r\n-- 1.42%. \r\ntabla :: [Float]\r\ntabla = [12.53, 1.42, 4.68, 5.86, 13.68, 0.69, 1.01, \r\n          0.70, 6.25, 0.44, 0.01,  4.97, 3.15, 6.71, \r\n          8.68, 2.51, 0.88, 6.87,  7.98, 4.63, 3.93, \r\n          0.90, 0.02, 0.22, 0.90,  0.52]\r\n\r\n-- (porcentaje n m) es el porcentaje de n sobre m. Por ejemplo,\r\n--    porcentaje 2 5  ==  40.0  \r\nporcentaje :: Int -> Int -> Float\r\nporcentaje n m = (fromIntegral n \/ fromIntegral m) * 100\r\n\r\n-- (letras xs) es la cadena formada por las letras de la cadena xs. Por\r\n-- ejemplo,  \r\n--    letras \"Esto Es Una Prueba\"  ==  \"EstoEsUnaPrueba\"\r\nletras :: String -> String\r\nletras xs = [x | x <- xs, elem x (['a'..'z']++['A'..'Z'])]\r\n\r\n-- (ocurrencias x xs) es el n\u00famero de veces que ocurre el car\u00e1cter x en\r\n-- la cadena xs. Por ejemplo, \r\n--    ocurrencias 'a' \"Salamanca\"  ==  4  \r\nocurrencias :: Char -> String -> Int\r\nocurrencias x xs = length [x' | x' <- xs, x == x']  \r\n\r\n-- (frecuencias xs) es la frecuencia de cada una de las letras de la\r\n-- cadena xs. Por ejemplo, \r\n--    *Main> frecuencias \"En Todo La Medida\"\r\n--    [14.3,0,0,21.4,14.3,0,0,0,7.1,0,0,7.1,\r\n--     7.1,7.1,14.3,0,0,0,0,7.1,0,0,0,0,0,0]\r\nfrecuencias :: String -> [Float]\r\nfrecuencias xs = \r\n    [porcentaje (ocurrencias x xs') n | x <- ['a'..'z']]\r\n    where xs' = [toLower x | x <- xs]\r\n          n   = length (letras xs)\r\n\r\n-- (chiCuad os es) es la medida chi cuadrado de las distribuciones os y\r\n-- es. Por ejemplo, \r\n--    chiCuad [3,5,6] [3,5,6]  ==  0.0\r\n--    chiCuad [3,5,6] [5,6,3]  ==  3.9666667\r\nchiCuad :: [Float] -> [Float] -> Float\r\nchiCuad os es = sum [((o-e)^2)\/e | (o,e) <- zip os es]\r\n\r\n-- (rota n xs) es la lista obtenida rotando n posiciones los elementos\r\n-- de la lista xs. Por ejemplo, \r\n--    rota 2 \"manolo\"  ==  \"noloma\"  \r\nrota :: Int -> [a] -> [a]\r\nrota n xs = drop n xs ++ take n xs\r\n\r\n-- (descifra xs) es la cadena obtenida descodificando la cadena xs por\r\n-- el anti-desplazamiento que produce una distribuci\u00f3n de letras con la\r\n-- menor deviaci\u00f3n chi cuadrado respecto de la tabla de distribuci\u00f3n de\r\n-- las letras en castellano. Por ejemplo, \r\n--    *Main> codifica 5 \"Todo Para Nada\"\r\n--    \"Ytit Ufwf Sfif\"\r\n--    *Main> descifra \"Ytit Ufwf Sfif\"\r\n--    \"Todo Para Nada\"\r\ndescifra :: String -> String\r\ndescifra xs =  codifica (-factor) xs\r\n where\r\n  factor = head (posiciones (minimum tabChi) tabChi)\r\n  tabChi = [chiCuad (rota n tabla') tabla | n <- [0..25]]\r\n  tabla' = frecuencias xs\r\n\r\nposiciones :: Eq a => a -> [a] -> [Int]\r\nposiciones x xs = \r\n    [i | (x',i) <- zip xs [0..], x == x']\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>En la clase de hoy de Inform\u00e1tica de 1\u00ba del Grado en Matem\u00e1ticas hemos comentado las soluciones a los 5 \u00faltimos ejercicios de la 4\u00aa relaci\u00f3n, que tratan sobre definiciones por comprensi\u00f3n, y los de la 5\u00aa relaci\u00f3n, que ampl\u00eda la codificaci\u00f3n C\u00e9sar vista en clase para incluir las may\u00fasculas. Los ejercicios, y sus soluciones,&#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":[186],"tags":[295],"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\/1677"}],"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=1677"}],"version-history":[{"count":4,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/1677\/revisions"}],"predecessor-version":[{"id":2917,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/1677\/revisions\/2917"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=1677"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=1677"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=1677"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}