Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#45 - Python #8141

Merged
merged 7 commits into from
Mar 28, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions Roadmap/45 - GITHUB OCTOVERSE/python/idiegorojas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""
# 45 - Github Octoverse
"""

# https://octoverse.github.com
# Utilizando el API de GitHub, crea un informe asociado a un usuario concreto.

# Se debe poder definir el nombre del usuario sobre el que se va a generar el informe.
# Crea un informe de usuario basándote en las 5 métricas que tú quieras, utilizando la información que te proporciona GitHub. Por ejemplo:
# Lenguaje más utilizado
# Cantidad de repositorios
# Seguidores/Seguidos
# Stars/forks
# Contribuciones


import requests
from datetime import datetime

def generate_github_report(username: str):

base_url = "https://api.github.com"

# Get user data
user_url = f"{base_url}/users/{username}"
response = requests.get(user_url)

if response.status_code != 200:
print(f"Error: No se pudo obtener información para el usuario {username}. Código: {response.status_code}")
return

user_data = response.json()

# Get repositories data
repos_url = f"{base_url}/users/{username}/repos"
repos_response = requests.get(repos_url)

if repos_response.status_code != 200:
print(f"Error: No se pudo obtener los repositorios para {username}")
repos = []
else:
repos = repos_response.json()

# Basic user info
name = user_data.get("name") or username
company = user_data.get("company") or "No especificado"
location = user_data.get("location") or "No especificado"
bio = user_data.get("bio") or "Sin biografía"
followers = user_data.get("followers", 0)
following = user_data.get("following", 0)
created_at = user_data.get("created_at")
updated_at = user_data.get("updated_at") # Fixed typo here
public_repos = user_data.get("public_repos", 0)

# Format dates
if created_at:
created_at = datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y")
if updated_at:
updated_at = datetime.strptime(updated_at, "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y")

# Calculate metrics
languages = {}
total_stars = 0
total_forks = 0

for repo in repos:
# Count stars and forks
total_stars += repo.get("stargazers_count", 0)
total_forks += repo.get("forks_count", 0)

# Count languages
language = repo.get("language")
if language:
languages[language] = languages.get(language, 0) + 1

# Find most used language
most_used_language = max(languages, key=languages.get) if languages else "No disponible"

# Print the report
print("\n" + "=" * 50)
print(f"REPORTE DE GITHUB PARA: {name}")
print("=" * 50)
print(f"Trabaja en: {company}")
print(f"Vive en: {location}")
print(f"Bio: {bio}")
print("\n--- MÉTRICAS ---")
print(f"1. Repositorios públicos: {public_repos}")
print(f"2. Lenguaje más utilizado: {most_used_language}")
print(f"3. Seguidores/Seguidos: {followers}/{following}")
print(f"4. Stars/Forks totales: {total_stars}/{total_forks}")
print(f"5. Perfil creado el: {created_at}")
print(f"Última actualización: {updated_at}")
print("=" * 50)

# Main program
username = input("Ingresa el username del usuario que deseas consultar en GitHub: ")
generate_github_report(username)
326 changes: 326 additions & 0 deletions Roadmap/46 - X VS BLUESKY/python/idiegorojas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
"""
# 46 - Bluesky vs X
"""
# Implementa un sistema que simule el comportamiento de estas redes sociales.
# Debes crear las siguientes operaciones:
# Registrar un usuario por nombre e identificador único.
# Un usuario puede seguir/dejar de seguir a otro.
# Creación de post asociado a un usuario. Debe poseer texto (200 caracteres máximo), fecha de creación e identificador único.
# Eliminación de un post.
# Posibilidad de hacer like (y eliminarlo) en un post.
# Visualización del feed de un usuario con sus 10 publicaciones más actuales ordenadas desde la más reciente.
# Visualización del feed de un usuario con las 10 publicaciones más actuales de los usuarios que sigue ordenadas desde la más reciente.
# Cuando se visualiza un post, debe mostrarse:
# ID de usuario
# nombre de usuario
# texto del post,
# fecha de creación
# número total de likes.
# Controla errores en duplicados o acciones no permitidas.
import datetime

class SocialMedia():
def __init__(self):
self.users = {} # Id User {name: user name}
self.posts = {} # {post: [id, description, created date]}
self.followers = {} # {user: [# followers]}


def create_user(self):
username = input("Ingresa tu nombre de usuario: ")

if username in self.users:
print(f"Lo sentimos el nombre de usuario {username} no esta disponible")
return False

user_id = len(self.users) + 1

self.users[username] = {"id": user_id, "name":username}
self.followers[username] = []

print(f"Usuario {username} creado exitosamente con el ID: {user_id}")
return True


def create_post(self):
username = input("Ingresa tu usuario: ")

if username not in self.users:
print(f"Lo sentimos el usuario {username} no se encuentra registrado")
return False

post_text = input("Ingresa el post (maximo 200 caracteres): ")

if len(post_text) > 200:
print("Lo sentimos el post excede el numero de caracteres. (Maximo 200)")
return False

post_id = len(self.posts) + 1

creation_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

self.posts[post_id] = {
"id": post_id,
"user_id": self.users[username]["id"],
"username": username,
"text": post_text,
"created_at": creation_date,
"likes": []
}

print(f"Post con ID: {post_id} creado exitosamente.")
return True

def follow_user(self):
follower = input("Ingresa tu nombre de usuario: ")

if follower not in self.users:
print(f"Lo sentimos, el usuario {follower} no existe")
return False

to_follow = input("Ingresa el nombre del usuario que deseas seguir: ")

if to_follow not in self.users:
print(f"Lo sentimos, el usuario {to_follow} no existe")
return False

if follower == to_follow:
print("No puedes seguirte a ti mismo")
return False

if to_follow in self.followers[follower]:
print(f"Ya estás siguiendo a {to_follow}")
return False

self.followers[follower].append(to_follow)
print(f"Ahora estás siguiendo a {to_follow}")
return True

def unfollow_user(self):
follower = input("Ingresa tu nombre de usuario: ")

if follower not in self.users:
print(f"Lo sentimos, el usuario {follower} no existe")
return False

to_unfollow = input("Ingresa el nombre del usuario que deseas dejar de seguir: ")

if to_unfollow not in self.followers[follower]:
print(f"No estás siguiendo a {to_unfollow}")
return False

self.followers[follower].remove(to_unfollow)
print(f"Has dejado de seguir a {to_unfollow}")
return True

def delete_post(self):
username = input("Ingresa tu nombre de usuario: ")

if username not in self.users:
print(f"Lo sentimos, el usuario {username} no existe")
return False

post_id = input("Ingresa el ID del post que deseas eliminar: ")

try:
post_id = int(post_id)
except ValueError:
print("El ID del post debe ser un número")
return False

if post_id not in self.posts:
print(f"El post con ID {post_id} no existe")
return False

if self.posts[post_id]["username"] != username:
print("No puedes eliminar un post que no te pertenece")
return False

del self.posts[post_id]
print(f"Post con ID {post_id} eliminado exitosamente")
return True

def like_post(self):
username = input("Ingresa tu nombre de usuario: ")

if username not in self.users:
print(f"Lo sentimos, el usuario {username} no existe")
return False

post_id = input("Ingresa el ID del post que deseas dar like: ")

try:
post_id = int(post_id)
except ValueError:
print("El ID del post debe ser un número")
return False

if post_id not in self.posts:
print(f"El post con ID {post_id} no existe")
return False

if username in self.posts[post_id]["likes"]:
print("Ya has dado like a este post")
return False

self.posts[post_id]["likes"].append(username)
print(f"Has dado like al post con ID {post_id}")
return True

def unlike_post(self):
username = input("Ingresa tu nombre de usuario: ")

if username not in self.users:
print(f"Lo sentimos, el usuario {username} no existe")
return False

post_id = input("Ingresa el ID del post que deseas quitar like: ")

try:
post_id = int(post_id)
except ValueError:
print("El ID del post debe ser un número")
return False

if post_id not in self.posts:
print(f"El post con ID {post_id} no existe")
return False

if username not in self.posts[post_id]["likes"]:
print("No has dado like a este post")
return False

self.posts[post_id]["likes"].remove(username)
print(f"Has quitado el like al post con ID {post_id}")
return True

def show_post(self, post_id):
if post_id not in self.posts:
print(f"El post con ID {post_id} no existe")
return False

post = self.posts[post_id]
print(f"ID de usuario: {post['user_id']}")
print(f"Nombre de usuario: {post['username']}")
print(f"Texto: {post['text']}")
print(f"Fecha de creación: {post['created_at']}")
print(f"Número de likes: {len(post['likes'])}")
return True

def user_feed(self):
username = input("Ingresa tu nombre de usuario: ")

if username not in self.users:
print(f"Lo sentimos, el usuario {username} no existe")
return False

# Encuentra todos los posts del usuario
user_posts = []
for post_id, post in self.posts.items():
if post["username"] == username:
user_posts.append((post_id, post["created_at"]))

# Ordena por fecha de creación (más reciente primero)
user_posts.sort(key=lambda x: x[1], reverse=True)

# Obtiene los 10 posts más recientes
recent_posts = user_posts[:10]

if not recent_posts:
print(f"El usuario {username} no tiene publicaciones")
return False

print(f"Feed de {username} (publicaciones propias):")
for idx, (post_id, _) in enumerate(recent_posts, 1):
print(f"\nPost {idx}:")
self.show_post(post_id)

return True

def following_feed(self):
username = input("Ingresa tu nombre de usuario: ")

if username not in self.users:
print(f"Lo sentimos, el usuario {username} no existe")
return False

# Obtiene la lista de usuarios seguidos
following = self.followers[username]

if not following:
print(f"El usuario {username} no sigue a nadie")
return False

# Encuentra todos los posts de los usuarios seguidos
followed_posts = []
for post_id, post in self.posts.items():
if post["username"] in following:
followed_posts.append((post_id, post["created_at"]))

# Ordena por fecha de creación (más reciente primero)
followed_posts.sort(key=lambda x: x[1], reverse=True)

# Obtiene los 10 posts más recientes
recent_posts = followed_posts[:10]

if not recent_posts:
print(f"Los usuarios seguidos por {username} no tienen publicaciones")
return False

print(f"Feed de {username} (publicaciones de usuarios seguidos):")
for idx, (post_id, _) in enumerate(recent_posts, 1):
print(f"\nPost {idx}:")
self.show_post(post_id)

return True

def main_menu(self):
menu = """
SISTEMA DE REDES SOCIALES
------------------------
1. Crear usuario
2. Crear post
3. Seguir a un usuario
4. Dejar de seguir a un usuario
5. Eliminar post
6. Dar like a un post
7. Quitar like a un post
8. Ver feed propio
9. Ver feed de usuarios seguidos
0. Salir
Selecciona una opción: """

while True:
option = input(menu)

if option == "1":
self.create_user()
elif option == "2":
self.create_post()
elif option == "3":
self.follow_user()
elif option == "4":
self.unfollow_user()
elif option == "5":
self.delete_post()
elif option == "6":
self.like_post()
elif option == "7":
self.unlike_post()
elif option == "8":
self.user_feed()
elif option == "9":
self.following_feed()
elif option == "0":
print("¡Hasta pronto!")
break
else:
print("Opción no válida. Intenta de nuevo.")

input("\nPresiona Enter para continuar...")

# Ejecutar el programa
if __name__ == "__main__":
app = SocialMedia()
app.main_menu()
92 changes: 92 additions & 0 deletions Roadmap/47 - CALENDARIO DE ADVIENTO/python/idiegorojas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""
# 47 - Calendario de adviento
"""
# 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 selecciona 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.

def crear_calendario():
# Crear un diccionario para representar el calendario
# Días del 1 al 24, inicialmente todos sin descubrir (False)
return {i: False for i in range(1, 25)}

def mostrar_calendario(calendario):
# Mostrar el calendario en una cuadrícula de 6 columnas
dias_por_fila = 6

for fila in range(0, 24, dias_por_fila):
dias_en_esta_fila = range(fila + 1, min(fila + dias_por_fila + 1, 25))

# Primera línea de asteriscos (parte superior de las cuadrículas)
for i, dia in enumerate(dias_en_esta_fila):
print("****", end=" " if i < len(dias_en_esta_fila) - 1 else "")
print()

# Línea con los números
for i, dia in enumerate(dias_en_esta_fila):
if calendario[dia]: # Si el día está descubierto
print("****", end=" " if i < len(dias_en_esta_fila) - 1 else "")
else:
print(f"*{dia:02d}*", end=" " if i < len(dias_en_esta_fila) - 1 else "")
print()

# Tercera línea de asteriscos (parte inferior de las cuadrículas)
for i, dia in enumerate(dias_en_esta_fila):
print("****", end=" " if i < len(dias_en_esta_fila) - 1 else "")
print()

# Añadir una línea en blanco entre filas, excepto después de la última fila
if fila + dias_por_fila < 24:
print()

def seleccionar_dia(calendario, dia):
if dia < 1 or dia > 24:
print("Día inválido. Debe estar entre 1 y 24.")
return calendario

if calendario[dia]:
print(f"El día {dia} ya ha sido descubierto.")
else:
calendario[dia] = True
print(f"¡Has abierto el día {dia}!")

return calendario

def main():
calendario = crear_calendario()

while True:
mostrar_calendario(calendario)

try:
opcion = input("Selecciona un día (1-24) o 'q' para salir: ")

if opcion.lower() == 'q':
break

dia = int(opcion)
calendario = seleccionar_dia(calendario, dia)

except ValueError:
print("Entrada inválida. Ingresa un número entre 1 y 24 o 'q' para salir.")

print("\n")

if __name__ == "__main__":
main()
246 changes: 246 additions & 0 deletions Roadmap/48 - ÁRBOL DE NAVIDAD/python/idiegorojas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
"""
# 48 - Arbol de navidad
"""
# Desarrolla un programa que cree un árbol de Navidad
# con una altura dinámica definida por el usuario por terminal.
# Ejemplo de árbol de altura 5 (el tronco siempre será igual):

# *
# ***
# *****
# *******
# *********
# |||
# |||

# El usuario podrá seleccionar las siguientes acciones:
# Añadir o eliminar la estrella en la copa del árbol (@)
# Añadir o eliminar bolas de dos en dos (o) aleatoriamente
# Añadir o eliminar luces de tres en tres (+) aleatoriamente
# Apagar (*) o encender (+) las luces (conservando su posición)
# Una luz y una bola no pueden estar en el mismo sitio

# Sólo puedes añadir una estrella, y tantas luces o bolas como tengan cabida en el árbol. El programa debe notificar cada una de las acciones (o por el contrario, cuando no se pueda realizar alguna).

import random

class ArbolNavidad:
def __init__(self, altura):
self.altura = altura
self.estrella = False # Sin estrella inicialmente
self.luces = [] # Lista de tuplas (fila, columna, encendida)
self.bolas = [] # Lista de tuplas (fila, columna)

def posicion_ocupada(self, fila, columna):
"""Comprobar si una posición ya tiene una decoración"""
if self.estrella and fila == 0 and columna == self.altura - 1:
return True

for luz_fila, luz_col, _ in self.luces:
if luz_fila == fila and luz_col == columna:
return True

for bola_fila, bola_col in self.bolas:
if bola_fila == fila and bola_col == columna:
return True

return False

def agregar_estrella(self):
"""Añadir una estrella a la copa del árbol"""
if self.estrella:
print("Ya hay una estrella en el árbol")
return False

self.estrella = True
print("Estrella añadida")
return True

def quitar_estrella(self):
"""Quitar la estrella de la copa del árbol"""
if not self.estrella:
print("No hay estrella para eliminar")
return False

self.estrella = False
print("Estrella eliminada")
return True

def agregar_bolas(self):
"""Añadir dos bolas aleatoriamente al árbol"""
posiciones_disponibles = []

# Encontrar posiciones disponibles para bolas
for fila in range(self.altura):
ancho = 2 * fila + 1
for col in range(ancho):
col_real = col + (self.altura - fila - 1)
if not self.posicion_ocupada(fila, col_real):
posiciones_disponibles.append((fila, col_real))

if len(posiciones_disponibles) < 2:
print("No hay suficiente espacio para añadir más bolas")
return False

# Seleccionar dos posiciones aleatorias
posiciones = random.sample(posiciones_disponibles, 2)
self.bolas.extend(posiciones)
print("Dos bolas añadidas aleatoriamente")
return True

def quitar_bolas(self):
"""Quitar dos bolas aleatoriamente del árbol"""
if len(self.bolas) < 2:
print(f"Solo hay {len(self.bolas)} bolas para eliminar")
return False

for _ in range(2):
if self.bolas:
posicion = random.choice(self.bolas)
self.bolas.remove(posicion)

print("Dos bolas eliminadas aleatoriamente")
return True

def agregar_luces(self):
"""Añadir tres luces aleatoriamente al árbol"""
posiciones_disponibles = []

# Encontrar posiciones disponibles para luces
for fila in range(self.altura):
ancho = 2 * fila + 1
for col in range(ancho):
col_real = col + (self.altura - fila - 1)
if not self.posicion_ocupada(fila, col_real):
posiciones_disponibles.append((fila, col_real))

if len(posiciones_disponibles) < 3:
print("No hay suficiente espacio para añadir más luces")
return False

# Seleccionar tres posiciones aleatorias
posiciones = random.sample(posiciones_disponibles, 3)
self.luces.extend([(fila, col, True) for fila, col in posiciones]) # Luces comienzan encendidas (+)
print("Tres luces añadidas aleatoriamente")
return True

def quitar_luces(self):
"""Quitar tres luces aleatoriamente del árbol"""
if len(self.luces) < 3:
print(f"Solo hay {len(self.luces)} luces para eliminar")
return False

for _ in range(3):
if self.luces:
posicion = random.choice(self.luces)
self.luces.remove(posicion)

print("Tres luces eliminadas aleatoriamente")
return True

def cambiar_luces(self, encender):
"""Encender o apagar las luces"""
if not self.luces:
print("No hay luces en el árbol")
return False

nuevo_estado = []
for fila, col, _ in self.luces:
nuevo_estado.append((fila, col, encender))

self.luces = nuevo_estado
print(f"Luces {'encendidas' if encender else 'apagadas'}")
return True

def dibujar(self):
"""Dibujar el árbol con todas las decoraciones"""
arbol = []

# Generar la forma básica del árbol
for fila in range(self.altura):
linea = [' '] * (2 * self.altura - 1)
ancho = 2 * fila + 1
col_inicio = self.altura - fila - 1

for col in range(ancho):
linea[col_inicio + col] = '*'

arbol.append(linea)

# Añadir el tronco
for _ in range(2):
linea = [' '] * (2 * self.altura - 1)
inicio_tronco = self.altura - 2
linea[inicio_tronco:inicio_tronco+3] = ['|', '|', '|']
arbol.append(linea)

# Añadir estrella si está presente
if self.estrella:
arbol[0][self.altura - 1] = '@'

# Añadir luces
for fila, col, encendida in self.luces:
if 0 <= fila < self.altura and 0 <= col < len(arbol[fila]):
arbol[fila][col] = '+' if encendida else '*'

# Añadir bolas
for fila, col in self.bolas:
if 0 <= fila < self.altura and 0 <= col < len(arbol[fila]):
arbol[fila][col] = 'o'

# Convertir a cadenas y devolver
return '\n'.join([''.join(linea) for linea in arbol])

def main():
print("Bienvenido al generador de árboles de Navidad")

while True:
try:
altura = int(input("Introduzca la altura del árbol (3-20): "))
if 3 <= altura <= 20:
break
print("La altura debe estar entre 3 y 20")
except ValueError:
print("Por favor, introduzca un número válido")

arbol = ArbolNavidad(altura)

while True:
print("\n" + arbol.dibujar() + "\n")
print("Seleccione una acción:")
print("1. Añadir estrella (@)")
print("2. Eliminar estrella")
print("3. Añadir bolas (o) aleatoriamente")
print("4. Eliminar bolas aleatoriamente")
print("5. Añadir luces (+) aleatoriamente")
print("6. Eliminar luces aleatoriamente")
print("7. Encender luces (+)")
print("8. Apagar luces (*)")
print("9. Salir")

opcion = input("Elección: ")

if opcion == '1':
arbol.agregar_estrella()
elif opcion == '2':
arbol.quitar_estrella()
elif opcion == '3':
arbol.agregar_bolas()
elif opcion == '4':
arbol.quitar_bolas()
elif opcion == '5':
arbol.agregar_luces()
elif opcion == '6':
arbol.quitar_luces()
elif opcion == '7':
arbol.cambiar_luces(True)
elif opcion == '8':
arbol.cambiar_luces(False)
elif opcion == '9':
print("¡Feliz Navidad!")
break
else:
print("Opción no válida")

if __name__ == "__main__":
main()