diff --git a/README.md b/README.md index 00338ac5d1..7d3218049f 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ ## Corrección y próximo ejercicio -> #### Lunes 25 de noviembre de 2024 a las 20:00 (hora España) desde **[Twitch](https://twitch.tv/mouredev)** -> #### Consulta el **[horario](https://discord.gg/6FfxAHA3?event=1305700498115919993)** por país y crea un **[recordatorio](https://discord.gg/6FfxAHA3?event=1305700498115919993)** +> #### Lunes 2 de diciembre de 2024 a las 20:00 (hora España) desde **[Twitch](https://twitch.tv/mouredev)** +> #### Consulta el **[horario](https://discord.gg/mtHpG4md?event=1308551460644065330)** por país y crea un **[recordatorio](https://discord.gg/mtHpG4md?event=1308551460644065330)** ## Roadmap @@ -80,7 +80,8 @@ |43|[GIT GITHUB CLI](./Roadmap/43%20-%20GIT%20GITHUB%20CLI/ejercicio.md)|[📝](./Roadmap/43%20-%20GIT%20GITHUB%20CLI/python/mouredev.py)|[▶️](https://youtu.be/Ct4GKpbqflI)|[👥](./Roadmap/43%20-%20GIT%20GITHUB%20CLI/) |44|[CUENTA ATRÁS MOUREDEV PRO](./Roadmap/44%20-%20CUENTA%20ATRÁS%20MOUREDEV%20PRO/ejercicio.md)|[📝](./Roadmap/44%20-%20CUENTA%20ATRÁS%20MOUREDEV%20PRO/python/mouredev.py)|[▶️](https://youtu.be/9wsXz4K8Q-4)|[👥](./Roadmap/44%20-%20CUENTA%20ATRÁS%20MOUREDEV%20PRO/) |45|[GITHUB OCTOVERSE](./Roadmap/45%20-%20GITHUB%20OCTOVERSE/ejercicio.md)|[📝](./Roadmap/45%20-%20GITHUB%20OCTOVERSE/python/mouredev.py)|[▶️](https://youtu.be/yj5ZFT_Xmcs)|[👥](./Roadmap/45%20-%20GITHUB%20OCTOVERSE/) -|46|[X VS BLUESKY](./Roadmap/46%20-%20X%20VS%20BLUESKY/ejercicio.md)|[🗓️ 25/11/24](https://discord.gg/6FfxAHA3?event=1305700498115919993)||[👥](./Roadmap/46%20-%20X%20VS%20BLUESKY/) +|46|[X VS BLUESKY](./Roadmap/46%20-%20X%20VS%20BLUESKY/ejercicio.md)|[📝](./Roadmap/46%20-%20X%20VS%20BLUESKY/python/mouredev.py)||[👥](./Roadmap/46%20-%20X%20VS%20BLUESKY/) +|47|[CALENDARIO DE ADVIENTO](./Roadmap/47%20-%20CALENDARIO%20DE%20ADVIENTO/ejercicio.md)|[🗓️ 02/12/24](https://discord.gg/mtHpG4md?event=1308551460644065330)||[👥](./Roadmap/47%20-%20CALENDARIO%20DE%20ADVIENTO/) ## Cursos en YouTube diff --git a/Roadmap/46 - X VS BLUESKY/python/mouredev.py b/Roadmap/46 - X VS BLUESKY/python/mouredev.py new file mode 100644 index 0000000000..1a04223632 --- /dev/null +++ b/Roadmap/46 - X VS BLUESKY/python/mouredev.py @@ -0,0 +1,185 @@ +from datetime import datetime + + +class SocialNetwork: + + def __init__(self): + self.post_id = 0 + self.users = {} + self.post = {} + + def register_user(self, user_id: str, name: str): + + if user_id in self.users: + print(f"El usuario con el ID {user_id} ya existe.") + return + + self.users[user_id] = { + "name": name, + "following": set(), + "followers": set(), + "post": [] + } + print( + f"Usuario con ID '{user_id}' y nombre '{ + name}' registrado correctamente." + ) + + def follow_user(self, user_id: str, follow_id: str): + + if user_id not in self.users or follow_id not in self.users: + print("Alguno de los usuarios no existe. No se puede realizar el follow.") + return + + self.users[user_id]["following"].add(follow_id) + self.users[follow_id]["followers"].add(user_id) + print( + f"{self.users[user_id]["name"]} ahora sigue a { + self.users[follow_id]["name"]}." + ) + + def unfollow_user(self, user_id: str, unfollow_id: str): + + if user_id not in self.users or unfollow_id not in self.users: + print("Alguno de los usuarios no existe. No se puede realizar el unfollow.") + return + + self.users[user_id]["following"].discard(unfollow_id) + self.users[unfollow_id]["followers"].discard(user_id) + print( + f"{self.users[user_id]["name"]} ha dejado de seguir a { + self.users[unfollow_id]["name"]}." + ) + + def create_post(self, user_id: str, text: str): + + if user_id not in self.users: + print(f"El usuario '{user_id}' no existe.") + return + + if len(text) > 200: + print("El post no puede tener más de 200 caracteres.") + return + + self.post_id += 1 + + post_id = self.post_id + + self.post[post_id] = { + "user_id": user_id, + "text": text, + "created_at": datetime.now(), + "likes": set() + } + + self.users[user_id]["post"].append(post_id) + + print("Post creado correctamente.") + + def delete_post(self, post_id: int): + + if post_id not in self.post: + print(f"El post con ID {post_id} no existe.") + return + + user_id = self.post[post_id]["user_id"] + self.users[user_id]["post"].remove(post_id) + del self.post[post_id] + print("Post eliminado correctamente.") + + def like_post(self, user_id: str, post_id: int): + + if user_id not in self.users: + print(f"El usuario '{user_id}' no existe.") + return + + if post_id not in self.post: + print(f"El post '{post_id}' no existe.") + return + + self.post[post_id]["likes"].add(user_id) + print(f"Nuevo like en post '{post_id}'.") + + def unlike_post(self, user_id: str, post_id: int): + + if user_id not in self.users: + print(f"El usuario '{user_id}' no existe.") + return + + if post_id not in self.post: + print(f"El post '{post_id}' no existe.") + return + + self.post[post_id]["likes"].discard(user_id) + print(f"Like eliminado en post '{post_id}'.") + + def view_user_feed(self, user_id: str): + + if user_id not in self.users: + print(f"El usuario '{user_id}' no existe.") + return + + feed = sorted( + (self.post[post_id] for post_id in self.users[user_id]["post"]), + key=lambda x: x["created_at"], + reverse=True + )[:10] + + for post in feed: + print(f""" +ID usuario: {post["user_id"]} +Usuario: {self.users[post["user_id"]]["name"]} +Texto: {post["text"]} +Fecha: {post["created_at"]} +Likes: {len(post["likes"])} + """) + + def view_following_feed(self, user_id: str): + + if user_id not in self.users: + print(f"El usuario '{user_id}' no existe.") + return + + following_post_ids = [] + + for following_id in self.users[user_id]["following"]: + following_post_ids.extend(self.users[following_id]["post"]) + + feed = sorted( + (self.post[post_id] for post_id in following_post_ids), + key=lambda x: x["created_at"], + reverse=True + )[:10] + + for post in feed: + print(f""" +ID usuario: {post["user_id"]} +Usuario: {self.users[post["user_id"]]["name"]} +Texto: {post["text"]} +Fecha: {post["created_at"]} +Likes: {len(post["likes"])} + """) + + +social_network = SocialNetwork() +social_network.register_user("mouredev", "Brais Moure") +social_network.register_user("manolo", "Manolo 87") + +social_network.create_post("mouredev", "Hola mundo!") +social_network.create_post("mouredev", "Hola mundo 2!") +social_network.create_post("mouredev", "Hola mundo 3!") + +social_network.create_post("manolo", "Hola mundo!") +social_network.create_post("manolo", "Hola mundo 2!") +social_network.create_post("manolo", "Hola mundo 3!") + +social_network.follow_user("manolo", "mouredev") + +social_network.like_post("manolo", 1) + +social_network.view_user_feed("mouredev") +social_network.view_following_feed("manolo") + +social_network.unlike_post("manolo", 1) + +social_network.view_following_feed("manolo") diff --git a/Roadmap/47 - CALENDARIO DE ADVIENTO/ejercicio.md b/Roadmap/47 - CALENDARIO DE ADVIENTO/ejercicio.md new file mode 100644 index 0000000000..6dd6438831 --- /dev/null +++ b/Roadmap/47 - CALENDARIO DE ADVIENTO/ejercicio.md @@ -0,0 +1,45 @@ +# #47 CALENDARIO DE ADVIENTO +> #### Dificultad: Fácil | Publicación: 25/11/24 | Corrección: 02/12/24 + +## Ejercicio + +``` +/* + * EJERCICIO: + * ¡Cada año celebramos el aDEViento! 24 días, 24 regalos para + * developers. Del 1 al 24 de diciembre: https://adviento.dev + * + * Dibuja un calendario por terminal e implementa una + * funcionalidad para seleccionar días y mostrar regalos. + * - El calendario mostrará los días del 1 al 24 repartidos + * en 6 columnas a modo de cuadrícula. + * - Cada cuadrícula correspondiente a un día tendrá un tamaño + * de 4x3 caracteres, y sus bordes serán asteríscos. + * - Las cuadrículas dejarán un espacio entre ellas. + * - En el medio de cada cuadrícula aparecerá el día entre el + * 01 y el 24. + * + * Ejemplo de cuadrículas: + * **** **** **** + * *01* *02* *03* ... + * **** **** **** + * + * - El usuario seleccioná qué día quiere descubrir. + * - Si está sin descubrir, se le dirá que ha abierto ese día + * y se mostrará de nuevo el calendario con esa cuadrícula + * cubierta de asteríscos (sin mostrar el día). + * + * Ejemplo de selección del día 1 + * **** **** **** + * **** *02* *03* ... + * **** **** **** + * + * - Si se selecciona un número ya descubierto, se le notifica + * al usuario. + */ +``` +#### Tienes toda la información extendida sobre el roadmap de retos de programación en **[retosdeprogramacion.com/roadmap](https://retosdeprogramacion.com/roadmap)**. + +Sigue las **[instrucciones](../../README.md)**, consulta las correcciones y aporta la tuya propia utilizando el lenguaje de programación que quieras. + +> Recuerda que cada semana se publica un nuevo ejercicio y se corrige el de la semana anterior en directo desde **[Twitch](https://twitch.tv/mouredev)**. Tienes el horario en la sección "eventos" del servidor de **[Discord](https://discord.gg/mouredev)**. \ No newline at end of file