Tabla de Contenidos
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 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 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
ytirarDesde
.
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 EasyIO.hs del curso Introductory Functional Programming for Physics Students )
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 Proyecto Gutemberg-Español donde hay muchos libros que ya no tienen derecho de copia.
Por ejemplo están Cuentos de Amor de Locura y de Muerte de Horacio Quiroga y 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: 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
, dondeesta x xs
decide si el elementox
está en la listaxs
(ver práctico 10). - Probar las funciones
tomaPalabra
,tiraEspacio
,tiraPalabra
y finalmentepartirPalabras
. - 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 utilizandotomar
, 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.