Página de Guillaume Hoffmann

View on GitHub

% Practico Haskell: un programa con entrada/salida y diccionarios

En este práctico vas a hacer un programa que tiene que tomar el camino a un archivo de texto en línea de comando, y que calcule las palabras más usadas en el archivo.

La idea es empaquetar ese programa con cabal.

Palabras más frecuentes en un texto

Vas a editar el módulo Main.hs. La idea es hacer un programa que lea un archivo de texto y muestre las 10 palabras más frecuentes.

Como archivos de texto podés bajar libros desde proyecto Gutenberg (https://www.gutenberg.org/browse/languages/es) en formato .txt, por ejemplo:

Se puede dividir el trabajo en las étapas siguientes:

  1. leer el contenido del archivo como una sola cadena de caracteres
  2. partir este contenido como lista de palabras
  3. procesar esta lista de palabras para contar cuántas veces aparece cada palabra
  4. ordenar las palabras de más frecuente a menos frecuente, y mostrar las más frecuentes

Para implementar el paso 3, vamos a usar la estructura de datos Map (diccionario) del módulo Data.Map.Strict. La idea es guardar las palabras y su cantidad de ocurrencias en un diccionario de tipo Map String Int.

Más precisamente, se implementará lo siguiente:

  1. Importá los módulos Data.Map.Strict y Data.List dándoles respectivamente el prefijo Map y List para evitar colisiones de nombres.
  2. Definí una función main que lee el contenido del primer archivo dado como argumento en línea de comando, y imprime las palabras del archivo como una lista de Strings. Indicación: buscá getArgs en Hoogle.
  3. Definí una función agregar :: Map.Map String Int -> String -> Map.Map String Int que agrega una palabra a un diccionario (posiblemente el diccionario ya tiene la palabra!). Ejemplos:

    agregar Map.empty "Hola"                     == fromList [("Hola",1)]
    agregar ( agregar Map.empty "Hola"  ) "Chau" == fromList [("Chau",1),("Hola",1)]
    agregar ( agregar Map.empty "Hola"  ) "Hola" == fromList [("Hola",2)]
    
  4. Definí la función agregarLista :: Map.Map String Int -> [String] -> Map.Map String Int que agrega repetitivamente las palabras dadas en una lista.

    Ejemplos:

    agregarLista Map.empty ["Hola"]        == fromList [("Hola",1)]
    agregarLista Map.empty ["Hola","Chau"] == fromList [("Chau",1),("Hola",1)]
    agregarLista Map.empty ["Hola","Hola"] == fromList [("Hola",2)]
    
  5. Modificá el main para agregar todas las palabras del archivo a un diccionario vacío para construir un diccionario que contenga todas las palabras del archivo con sus respetivas frecuencias.
  6. Definí la función top10 :: Map.Map String Int -> [(Int, String)] que devuelva las 10 palabras más frecuentes del diccionario m.
  7. Imprimí el top 10 de las palabras del archivo en la salida estándar.

Después de terminar cada paso podés mostrar en la salida estándar lo que llegaste a definir.

Mejoras

Para mejorar este programa, podés implementar los siguientes puntos:

Por ejemplo, no te sirve que tu programa crea que “Hola,” (con la coma pegada) es una palabra; tampoco te sirve que “Hola” y “hola” sean consideradas como dos palabras distintas. Podés también evitar que “alumno”, “alumna”, “alumnos” y “alumnas” sean consideradas como cuatro palabras distintas.