TP2 - Algo Twitter
Consigna
En este Trabajo Práctico 2, se requiere el desarrollo de un sistema inspirado en la popular red social Twitter. El objetivo es implementar una aplicación que permita a los usuarios crear, buscar y eliminar tweets, simulando algunas de las funcionalidades básicas de la red social.
El desafío principal radica no solo en la correcta implementación de estas operaciones, sino también en la optimización del rendimiento. La búsqueda y eliminación de tweets deberán superar la eficiencia de una búsqueda lineal simple, es decir, se espera que la búsqueda y eliminación de tweets, sea mejor que O(N) siendo N la cantidad total de tokens de todos los tweets
Importante:
Este Trabajo Práctico utiliza un sistema de pruebas automáticas para evaluar la correcta implementación. Por ello, es crítico respetar estrictamente los formatos de salida especificados. Los menús y mensajes deben ser exactamente iguales a los ejemplos presentados. El cumplimiento de estos formatos es un requisito obligatorio para la aprobación.
Menú Principal
El menú principal debe ofrecer las siguientes opciones:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
A continuación, se detalla el funcionamiento de cada opción, junto con el contrato que deben cumplir para que el TP sea considerado válido.
1. Crear Tweet: Permite al usuario ingresar un tweet, el cual se almacenará en memoria
Ejemplo de uso:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 1
Ingrese el tweet a almacenar:
>>> Hola como estas
OK 0
Seleccione una opcion:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 1
Ingrese el tweet a almacenar:
>>> Hola como estás vos?
OK 1
Seleccione una opcion:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 1
Ingrese el tweet a almacenar:
>>> Todo bien, y vos???
OK 2
El usuario ingresa el número 1 para seleccionar la opción de crear un tweet, seguido del contenido del tweet. El programa debe responder con un mensaje de confirmación, incluyendo un número que identifica de manera única al tweet almacenado. Es crucial respetar el formato OK id_tweet
para asegurar el correcto funcionamiento de las pruebas automáticas.
Es importante destacar que:
- El tweet original siempre debe ser mostrado al usuario de la misma manera en la que fue escrito, respetando caracteres especiales, mayúsculas y minúsculas.
- Para la búsqueda se debe utilizar una versión normalizada del tweet. Ésta versión debe contener todas las letras en minúscula y eliminar cualquier caracter que no sea una letra o un número. Por ejemplo, el tweet "Hola, Cómo ESTAS?!?!" se normalizará como "hola como estas". Esto implica que se debe tener en cuenta cambios en mayúsculas y minúsculas para que por ejemplo "despues" y "Despues" se consideren iguales. No debe realizarse un esfuerzo para identificar errores ortográficos, por lo que "despues" y "depsues" se consideran diferentes.
Otras consideraciones importantes:
- Un tweet que después de ser normalizado, resulte vacío, no debe ser almacenado. Éste señaliza un error en la entrada del usuario. Por ejemplo, si el usuario ingresa "!!!", el programa debe mostrar un mensaje de error (
Input invalido.
) (ver Restricciones del formato de salida del programa) y volver a solicitar la entrada. - Al borrar un tweet, su ID queda inutilizado. Cuando se agregue un nuevo tweet, se debe tomar el próximo ID incremental, sin reutilizar los IDs de tweets borrados.
2. Buscar Tweet: Permite al usuario ingresar una o varias palabras clave para buscar en los tweets almacenados
Ejemplo de ejecución:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 2
Ingrese la/s palabra/s clave a buscar:
>>> Hola
Resultado de la busqueda
0. Hola como estas
1. Hola como estas vos?
En este caso, el usuario ingresa el número 2 para seleccionar la opción de buscar un tweet, seguido de la(s) palabra(s) clave a buscar. El programa debe mostrar todos los tweets (con su ID correspondiente) que contengan la(s) palabra(s) clave ingresada(s). La búsqueda debe realizarse utilizando la versión normalizada de los tweets y de las palabras clave. La salida del programa debe incluir un mensaje de confirmación, seguido de los tweets encontrados, respetando el siguiente formato:
Resultado de la busqueda:
<id_tweet>. tweet
Si se ingresa un tweet que no existe, se debe mostrar el mensaje No se encontraron tweets.
(NO_ENCONTRADOS
) y volver a solicitar la entrada. Por ejemplo:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 2
Ingrese la/s palabra/s clave a buscar:
>>> auto
No se encontraron tweets.
3. Eliminar Tweet: Permite al usuario ingresar una palabra clave y luego seleccionar los tweets que contienen esa palabra para eliminarlos
Ejemplo de uso:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 3
Ingrese el tweet a eliminar:
>>> vos
Resultado de la busqueda:
1. Hola como estas vos?
2. Todo bien, y vos???
Ingrese los numeros de tweets a eliminar:
>>> 2
Tweets eliminados:
2. Todo bien, y vos???
El usuario ingresa el número 3 para seleccionar la opción de eliminar un tweet, seguido de la palabra clave para buscar los tweets a eliminar. El programa muestra los tweets que contienen esa palabra clave y solicita al usuario que ingrese los números de los tweets que desea eliminar. La salida del programa debe ser un mensaje de confirmación, seguido de los tweets eliminados, respetando el siguiente formato:
Tweets eliminados:
<id_tweet>. tweet
De la misma manera que al buscar, si no se encuentran tweets que contengan la palabra clave, se debe mostrar el mensaje No se encontraron tweets.
(NO_ENCONTRADOS
) y volver a solicitar la entrada. Por ejemplo:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 3
Ingrese el tweet a eliminar:
>>> auto
No se encontraron tweets.
3.1. Distintos casos de eliminación de tweets
Al eliminar tweets, se deben considerar las siguientes opciones:
- Si se ingresa un número de tweet que no existe o que no está dentro de los tweets mostrados como resultado de la búsqueda, se debe mostrar un mensaje de error y volver a solicitar el ingreso de los números de tweets a eliminar. Por ejemplo, para los siguientes tweets:
0. hola como estas
1. hola como estas vos
2. todo bien y vos
Si se intenta eliminar la palabra clave vos
:
Ingrese el tweet a eliminar:
>>> vos
Resultado de la busqueda:
1. hola como estas vos
2. todo bien y vos
Ingrese los numeros de tweets a eliminar:
>>> 3
Numero de tweet invalido.
Ingrese los numeros de tweets a eliminar:
>>>
- Eliminación múltiple: Permite eliminar varios tweets en una misma operación, utilizando el formato
<id_tweet1>,<id_tweet2>,...,<id_tweetN>
. Por ejemplo, para los siguientes tweets que contienen la palabra claveauto
:
0. ahi va el auto de ivan
1. que auto te compraste
2. me prestas el auto
Si el usuario ingresa 1,2
, se eliminan los tweets 1 y 2, quedando el siguiente resultado:
Tweets eliminados:
1. que auto te compraste
2. me prestas el auto
El tweet 0 permanece almacenado.
- Eliminación por rango: Permite eliminar un rango de tweets en una misma operación, utilizando el formato
<id_tweet1>-<id_tweetN>
, donde<id_tweet1>
debe ser menor o igual que<id_tweetN>
. Por ejemplo, para los siguientes tweets que contienen la palabra clavevos
:
0. hola como estas vos
1. todo bien y vos
2. vos como andas
3. vos que haces
4. vos que onda
Si el usuario ingresa 1-3
, se eliminan los tweets 1, 2 y 3, resultando en:
Tweets eliminados:
1. todo bien y vos
2. vos como andas
3. vos que haces
Los tweets 0 y 4 permanecen almacenados.
- Se deben poder combinar distintas formas de eliminación en una misma operación. Por ejemplo:
>>> 1-5, 6, 7-10, 15, 17
Se eliminarán los tweets del 1 al 5, el 6, del 7 al 10, el 15 y el 17.
Importante:
-
Si el usuario no ingresa nada o el input esta mal por la razón que sea, se debe mostrar el mensaje de input inválido y volver a pedir rango.
-
La validación de entrada para el borrado de tweets se realiza en dos niveles:
-
Validación del formato de entrada (
INPUT_INVALIDO
):- Si el input no respeta el formato especificado (números separados por comas y/o rangos con guiones)
- Si se ingresan caracteres no numéricos
- Si el formato del rango es incorrecto
- Si la entrada no tiene sentido semántico
El sistema mostrará el mensaje
Input invalido.
y solicitará nuevamente la entrada.
-
Validación de existencia de tweets (
NUMERO_INVALIDO
):- Si uno o más de los IDs especificados no corresponden a tweets existentes
- Si se intenta eliminar un tweet que ya fue borrado
El sistema mostrará el mensaje
Numero de tweet invalido.
y solicitará nuevamente la entrada.
-
El programa debe manejar rangos repetidos o el mismo rango sin afectar el funcionamiento. Por ejemplo, si el usuario ingresa "1-3,2-4", el programa debe eliminar los tweets 1, 2, 3 y 4 sin errores ni duplicaciones. De la misma forma, si se ingresa "1-1", el programa debe eliminar solo el tweet 1.
- Todo lo que no suponga una eliminación completa de todos los tweets que se ingresen, implica que no se borra nada. En otras palabras: o se borra todo lo ingresado, o no se borra nada.
4. Salir: Finaliza el programa
La salida del programa debe ser el mensaje Finalizando...
, terminando la ejecución del programa.
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 4
Finalizando...
Regresar
El comando **
permite volver al menú principal desde cualquier submenú. Si se ingresa en el menú principal, se considera un input inválido.
Ejemplo:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 3
Ingrese el tweet a eliminar:
>>> **
Selecciona una de las siguientes opciones
1. Crear tweet
2. Buscar tweet
3. Eliminar Tweet
4. Salir
>>> **
Input invalido.
Almacenamiento de Tweets
Para este Trabajo Práctico, los tweets deben almacenarse en memoria durante la ejecución del programa. Al finalizar la ejecución, todos los tweets se perderán, y cada vez que se inicie el programa, la cantidad de tweets será nula.
Tokenización
Para la búsqueda y eliminación de Tweets, se utilizará el recurso de Tokenización. Éste proceso divide un texto en unidades más pequeñas, llamadas "tokens", que pueden ser palabras, frases o cualquier otro elemento significativo. Se admiten dos tipos de tokenización:
-
Tokenización por palabras: El texto se divide en palabras individuales. Por ejemplo, el tweet "hola como estas" se tokeniza como
["hola", "como", "estas"]
. -
Tokenización por segmentos: Cada palabra del texto se divide en segmentos de longitud mínima de N caracteres. Se debe asumir, que la longitud mínima de cada segmento, quedará fijo en N=3. Por ejemplo, el tweet "hola como estas" con la longitud de segmento de 3, se tokeniza como:
[
"hol", "hola", "ola",
"com", "como", "omo",
"est", "esta", "estas", "sta", "stas", "tas"
]
Uso de los dos tipos de Tokenización
Para cada palabra que se quiera buscar, se intentará buscar tanto en la tokenización por palabras como por segmentos, sin priorizar ninguna por sobre la otra.
Ejemplo
Suponiendo los siguientes tweets almacenados:
0. "hola como estas"
1. "autos de matias"
Y se desea buscar la palabra "Auto".
-
Tokenización por palabras:
- Tweet 0:
["hola", "como", "estas"]
- Tweet 1:
["autos", "de", "matias"]
La palabra "Auto" no se encuentra en ninguno de los tokens generados por la tokenización por palabras.
- Tweet 0:
-
Tokenización por segmento (con longitud de segmento de 3):
- Tweet 0:
['hol', 'hola', 'ola', 'com', 'como', 'omo', 'est', 'esta', 'estas', 'sta', 'stas', 'tas']
- Tweet 1:
['aut', 'auto', 'autos', 'uto', 'utos', 'tos', 'mat', 'mati', 'matia', 'matias', 'ati', 'atia', 'atias', 'tia', 'tias', 'ias']
La palabra "Auto" se encuentra en el token "auto" del Tweet 1.
- Tweet 0:
Por lo tanto, el resultado de la búsqueda será:
Resultado de la búsqueda:
1. autos de matias
Búsqueda de múltiples tokens
Además, se permitirá buscar consultar por varios tokens separados por un espacio entre cada uno.
Ejemplo
Supongamos que tenemos los siguientes tweets almacenados:
0. "hola como estas"
1. "esperalo un poco"
2. "club hermanos peralta"
Y se desea buscar las palabras "Peral" y "Club".
>>> 2
Ingrese la/s palabra/s clave a buscar:
>>> Peral Club!!!
- Tokenización por palabras:
Tweet 0: ["hola", "como", "estas"]
Tweet 1: ["esperalo", "un", "poco"]
Tweet 2: ["club", "hermanos", "peralta"]
La palabra "peral" no se encuentra en ninguno de los tokens generados por la tokenización por palabras, pero "club" se encuentra en el tweet 2.
- Tokenización por segmentos (con longitud de segmento de, por ejemplo, N = 5):
Tweet 0: ['estas']
Tweet 1: ['esper', 'espera', 'esperal', 'esperalo', 'spera', 'speral', 'speralo', 'peral', 'peralo', 'eralo']
Tweet 2: ['herma', 'herman', 'hermano', 'hermanos', 'erman', 'ermano', 'ermanos', 'rmano', 'rmanos', 'manos', 'peral', 'peralt', 'peralta', 'eralt', 'eralta', 'ralta']
La palabra "peral" se encuentra en uno de los segmentos de los tweets 1 y 2.
Por lo tanto, el resultado de la búsqueda será:
Resultado de la búsqueda:
2. club hermanos peralta
Aclaración del funcionamiento de búsqueda múltiple
Supongamos que tenemos los siguientes tweets almacenados:
0. "hola como estas"
1. "esperalo un poco"
2. "club hermanos peralta"
Si se busca:
Peral Club!!
El resultado esperado es:
Resultados de la busqueda:
2. "club hermanos peralta"
En cambio, si se busca:
Peral
El resultado esperado será:
Resultados de la busqueda:
1. "esperalo un poco"
2. "club hermanos peralta"
Esto implica que si se busca "Peral" y "Club", el resultado es el tweet 2, pero si se busca solo "Peral", el resultado son los tweets 1 y 2. El resultado de la búsqueda múltiple debe ser un tweet que contenga todos y cada uno de los tokens buscados. En este caso, el tweet 2 contiene tanto "Peral" como "Club".
Velocidad de Búsqueda y Eliminación
La implementación de la búsqueda y eliminación debe superar la velocidad de la búsqueda lineal siempre que sea posible. Se busca aprovechar las características de ciertas estructuras de datos para agilizar las operaciones aquí mencionadas. Este requisito es obligatorio para la aprobación del Trabajo Práctico.
Restricciones del formato de salida del programa
Para que sus trabajos pasen las pruebas del corrector automático, es muy importante mantener el formato utilizado en los ejemplos. Respetar el formato implica que todo lo que el programa muestre por pantalla debe ser exactamente igual a los ejemplos, sin textos adicionales ni cambios en los mensajes. Incluso pequeñas diferencias, como un espacio de más, un salto de línea extra o una palabra diferente, pueden hacer que las pruebas automáticas fallen.
Para facilitar esto, se proporcionan las constantes globales utilizadas en los tests. Utilícenlas en sus programas para evitar problemas de formato.
NUMERO_INVALIDO = "Numero de tweet invalido."
NO_ENCONTRADOS = "No se encontraron tweets."
INPUT_INVALIDO = "Input invalido."
FIN = "Finalizando..."
RESULTADOS_BUSQUEDA = "Resultados de la busqueda:"
TWEETS_ELIMINADOS = "Tweets eliminados:"
ATRAS = '**'
Es importante notar que no todos los textos que aparecen en los ejemplos se dan como constantes en esta sección. Se debe distinguir entre el texto que el programa muestra como salida (por ejemplo, a través de la función print
) y el texto que el usuario ingresa como entrada (por ejemplo, a través de la función input
). El formato de la salida debe coincidir exactamente con los ejemplos proporcionados.
El formato de la entrada es más flexible y puede variar, siempre y cuando el programa pueda procesarla correctamente. Esto implica que el mensaje que se utiliza en un input
no necesita seguir estos lineamientos.
Por ejemplo, Ingrese la/s palabra/s clave a buscar: no figura como constante, dado que se utiliza en el input
y no afecta el resultado de las pruebas automáticas. Sin embargo, el mensaje que se muestra al usuario como salida sí debe coincidir con los ejemplos.
Por eso, tener muy en cuenta que sobre todo lo que se haga print
, será evaluado por el corrector automático. Utilizar la salida por pantalla únicamente para cuestiones relacionadas a la consigna.
Consejo: Si vas a a debuggear tu código con prints, asegurate de sacarlos antes de entregar, ya que pueden afectar a la corrección de las pruebas automáticas.
Input inválido (INPUT_INVALIDO
)
Si el usuario ingresa un número que no corresponde a ninguna de las opciones del menú, se debe mostrar el mensaje Input invalido.
y volver a solicitar la opción. Además, cualquier entrada que no cumpla con el formato esperado (por ejemplo, al eliminar tweets) debe ser considerada como un input inválido. Esto incluye entradas vacías, caracteres no válidos así como también tweets que luego de su normalización resulten en vacío. En estos casos, se debe mostrar el mensaje Input invalido.
y volver a solicitar la opción.
Por ejemplo, si el usuario ingresa un número decimal o un texto en lugar de un número entero, se debe mostrar este mensaje de error:
1. Crear Tweet
2. Buscar Tweet
3. Eliminar Tweet
4. Salir
>>> 5
Input invalido.
En resumen, todo lo que suponga una "no acción" tiene que lanzar Input invalido.
y debe volver a solicitar el reintento de la misma acción
Es decir, si estaba por hacer una búsqueda o agregado de un tweet, y el input es invalido, se debe repetir la búsqueda del tweet, si es un input invalido en el main menu, se debe reintentar acción sobre el main menu, lo mismo con el rango
El mismo comportamiento aplica a Numero de tweet invalido.
cuando se ingresa un rango correcto, pero que tiene elementos inválidos. Se debe volver a requerir el rango.
Restricciones de entrega
- El programa nunca debe finalizar con una excepción. En el caso de un error, se debe mostrar por pantalla al usuario el mensaje apropiado según fue especificado.
- No se permite el uso de ninguna biblioteca externa.
- El código debe ser eficiente, eligiendo las estructuras correctas para la solución de los problemas correspondientes.
- La entrega debe pasar todas las pruebas del corrector automático para ser considerada como tal.
- El código debe estar correctamente modularizado, documentado, y seguir las convenciones y buenas prácticas establecidas por el lenguaje y el curso.
- El uso de módulos de la biblioteca estándar de Python deberá ser previamente autorizado por un docente.
- No se permite el uso del operador de argumentos
*
de la forma funcion(*argumentos). - No se permite el uso de variables globales (sí el de constantes!).
- No se permite el uso de
eval
.
Entrega
La entrega como tal, puede variar según como haya decidido quien implementa el trabajo, puede ser uno o varios archivos.
Lo único que se debe tener en cuenta es que el punto de entrada del TP es un archivo que se llame: algo_twitter.py
y que empiece su ejecución con la función main()
- Se deberán entregar únicamente los archivos .py que se utilicen. Siempre debe existir el archivo
algo_twitter.py
que contengamain()
- La entrega se hará utilizando el formulario de entregas bajo la sección TP2.
- Una vez realizada la entrega, el sistema correrá las pruebas automáticas y te indicará si tu entrega cumple con las condiciones o no. Esto será inmediato, así que no es necesario cerrar la página ni esperar un mail.
- Si la entrega no cumple con las condiciones, podrás corregir y reenviar la entrega las veces que sea necesario hasta que cumpla con las condiciones, siempre y cuando se entregue antes de la primera o segunda fecha límite. Los detalles de los problemas encontrados en la entrega serán indicados por el sistema en el momento de la entrega.
Material
Este archivo contiene la base del trabajo práctico con las constantes y la definición del main necesarias para la entrega.