====== Clase 4 ====== ===== Plan para hoy ===== * Soluciones en la Wiki: estado. * Contar frecuencia de palabras. * Ejercicios. * Como va a ser el parcialito 3 en máquina. ===== Soluciones en la Wiki del Práctico 8: estado ====== * En [[introalg:rincon|Wiki de Scripts Haskell]] ya tenemos casi todos los ejercicios resueltos. * Probarlos, criticarlos, mejorarlos. * Hay muchas resoluciones para cada ejercicio, mirarlas y compararlas. ===== Clase ===== Nos proponemos hacer un programa funcional que **cuente la frecuencia de las ocurrencias de palabras**. frecuencia :: [Palabra] -> [(Palabra,Int)] Main> frecuencia ["hola","que","hola"] [("hola",2),("que",1)] Donde ''Palabra'' es un //sinónimo de tipo//, en este caso de un ''String'', y sirve para mejorar la legibilidad del código. type Palabra = String Para hacer más fácil el uso de esta función tomamos de [[http://www.cs.kent.ac.uk/people/staff/sjt/craft2e/|Haskell The Craft of Functional Programming]] por Simon Thompson, la definción de una función que **parte una cadena en palabras**. espacio :: [Char] espacio = ['\n','\t',' '] esta :: Eq a => a -> [a] -> Bool -- Definirlo! -- Tambien podemos escribirlo como tomaPalabra :: [Char] -> [Char] tomaPalabra :: String -> String tomaPalabra [] = [] tomaPalabra (x:xs) | esta x espacio = [] | otherwise = x : tomaPalabra xs tiraPalabra :: String -> String tiraPalabra [] = [] tiraPalabra (x:xs) | esta x espacio = x:xs | otherwise = tiraPalabra xs tiraEspacio :: String -> String tiraEspacio [] = [] tiraEspacio (x:xs) | esta x espacio = tiraEspacio xs | otherwise = x:xs -- Declaracion de tipos type Palabra = String partirPalabras :: String -> [Palabra] partirPalabras st = partirPalabras' (tiraEspacio st) partirPalabras' :: String -> [Palabra] partirPalabras' [] = [] partirPalabras' st = (tomaPalabra st) : partirPalabras' (tiraEspacio (tiraPalabra st)) Todas estas definciones las metemos en el archivo ''frec.hs''. Notamos: * La definición de una lista de //caracteres// ''Char''. * Las tres funciones son muy parecidas en su forma y podríamos **generalizar** con ''tomarHasta'' y ''tirarDesde''. Una vez definida la función ''esta'' podemos probar las funciones. Main> tomaPalabra "Despues de tres dias" "Despues" Main> tiraEspacio "Despues de tres dias" "Despues de tres dias" Main> tiraEspacio " Despues de tres dias" "Despues de tres dias" Main> tiraPalabra " Despues de tres dias" " Despues de tres dias" Main> tiraPalabra "Despues de tres dias" " de tres dias" Main> partirPalabras "hola" ["hola"] Main> partirPalabras "hola que tal" ["hola","que","tal"] Main> partirPalabras " hola que tal " ["hola","que","tal"] Finalmente tenemos que definir la funcion que computa la frecuencia frecuencia :: [Palabra] -> [(Palabra,Int)] Por ejemplo Main> frecuencia ["hola","que","hola"] [("hola",2),("que",1)] Main> frecuencia (partirPalabras "Despues de tres dias Nebel decidio aclarar de una vez ese estado de osas, y aprovecho para ello un momento en que Lidia no estaba.") [("estaba.",1),("no",1),("Lidia",1),("que",1),("en",1),("momento",1),("un",1),("ello",1),("para",1),("aprovecho",1),("y",1),("osas,",1),("de",3),("estado",1),("ese",1),("vez",1),("una",1),("aclarar",1),("decidio",1),("Nebel",1),("dias",1),("tres",1),("Despues",1)] Para probar ejemplos más largos podemos agregar una función que dado el nombre de un archivo, devuelve un ''String'' con ese archivo (tomado de [[http://www.cs.chalmers.se/~rjmh/Teaching/Fysiker/EasyIO.hs|EasyIO.hs]] del curso //Introductory Functional Programming for Physics Students// 8-O) \\ Este código debe estar **al inicio del script**. import IOExts leeArchivo :: String -> String leeArchivo nombre = unsafePerformIO$ readFile nombre Para obtener textos largos e interesantes tenemos el [[http://www.gutenberg.org/browse/languages/es|Proyecto Gutemberg-Español]] donde hay muchos libros que ya no tienen derecho de copia. \\ Por ejemplo están [[http://www.gutenberg.org/files/13507/13507.txt|Cuentos de Amor de Locura y de Muerte]] de Horacio Quiroga y [[http://www.gutenberg.org/etext/14765|El Gaucho Martín Fierro]] de José Hernandez. Hay que tener cuidado con la **codificación** pues no todas funcionan.\\ Por ejemplo ''UTF8'' es una codificación posible: {{:introalg:14765-utf8.txt|Martín Fierro en UTF8}}, y calculamos la lista de frecuencias. Main> frecuencia (partirPalabras (leeArchivo "14765-utf8.txt")) ===== Ejercicios ===== * Definir la función ''esta : Eq a => a -> [a] -> Bool'', donde ''esta x xs'' decide si el elemento ''x'' está en la lista ''xs'' (ver práctico 10). * Probar las funciones ''tomaPalabra'', ''tiraEspacio'', ''tiraPalabra'' y finalmente ''partirPalabras''. * Definir la función ''frecuencia :: [Palabra] -> [(Palabra,Int)]'', que devuelve la frecuencia de cada palabra. Puede ser útil definir la función ''agregarOcurrencia :: Palabra -> [(Palabra,Int)] -> [(Palabra,Int)]'' que dada una palabra y una lista de frecuencias, suma esta palabra a la lista de frecuencias. \\ Por ejemplo: agregarOcurrencia "que" [("hola",2), ("que",1)] = [("hola",2), ("que",2)] agregarOcurrencia "hola" [] = [("hola",1)] agregarOcurrencia "que" [("hola",2)] = [("hola",2), ("que",1)] * (*) Modificar la función ''ordenar'' para que ordene una lista de pares ''[(Palabra,Int)]'' en su segunda coordenada, y utilizando ''tomar'', obtener las 10 palabras más usadas del //corpus//. * (* *) Modificar el programa para que tome un **parámetro de entrada** con el nombre del archivo y devuelva la tabla de frecuencias ordenadas de mayor a menor. ===== ?Como será el parcialito 3 en máquina? ===== * Ejercicios sencillos del tipo que estuvimos trabajando en clase. * Se evalua la corrección de la solucion y tienen que explicar como funciona. * Como siempre se (A)prueba o (N)Desaprueba. * Cada uno en su turno.