def obtener_tareas():
    """
    Inicializa y retorna una lista de tareas de ejemplo.

    Parámetros:
        Ninguno.

    Retorna:
        list: Una lista de diccionarios, donde cada diccionario representa una tarea
              con las claves 'descripcion' (str) y 'completada' (bool).
    """
    tareas_iniciales = [
        {"descripcion": "Leer el Capítulo 11 sobre funciones", "completada": True},
        {"descripcion": "Programar el gestor de tareas en Python", "completada": False},
        {"descripcion": "Redactar el informe de buenas prácticas", "completada": False}
    ]
    return tareas_iniciales


def mostrar_tareas(lista_tareas):
    """
    Imprime en consola todas las tareas numeradas junto con su estado actual.

    Parámetros:
        lista_tareas (list): Lista de diccionarios con las tareas registradas.

    Retorna:
        None: Esta función no retorna valores, solo imprime en pantalla.
    """
    print("\n--- LISTA DE TAREAS ---")
    if not lista_tareas:
        print("No hay tareas registradas.")
        return

    # Enumerate permite obtener el índice (iniciando en 1 para el usuario) y el diccionario
    for i, tarea in enumerate(lista_tareas, start=1):
        estado = "[X]" if tarea["completada"] else "[ ]"
        print(f"{i}. {estado} {tarea['descripcion']}")
    print("-----------------------")


def agregar_tarea(lista_tareas, descripcion):
    """
    Crea una nueva tarea pendiente y la agrega a la lista existente.

    Parámetros:
        lista_tareas (list): Lista actual de tareas.
        descripcion (str): Texto descriptivo de la nueva tarea.

    Retorna:
        list: La lista de tareas actualizada con el nuevo elemento.
    """
    nueva_tarea = {
        "descripcion": descripcion,
        "completada": False
    }
    lista_tareas.append(nueva_tarea)
    print(f"-> Tarea '{descripcion}' agregada exitosamente.")
    return lista_tareas


def marcar_completada(lista_tareas, posicion):
    """
    Cambia el estado 'completada' a True de una tarea según su posición visual.
    Incluye manejo de excepciones para posiciones fuera de rango.

    Parámetros:
        lista_tareas (list): Lista actual de tareas.
        posicion (int): Número de la tarea mostrado al usuario (base 1).

    Retorna:
        None: Modifica la lista original por referencia sin retornar nada.
    """
    try:
        # Validar que el usuario no ingrese números negativos o cero
        if posicion < 1:
            raise IndexError
            
        # Ajustar la posición (base 1) al índice real de Python (base 0)
        indice_real = posicion - 1
        lista_tareas[indice_real]["completada"] = True
        print(f"-> Tarea #{posicion} marcada como completada.")
        
    except IndexError:
        print(f"Error: La posición {posicion} no existe en la lista. Intente de nuevo.")


def contar_tareas_pendientes(lista_tareas, indice=0):
    """
    Calcula de forma recursiva el número total de tareas que aún no han sido completadas.

    Parámetros:
        lista_tareas (list): Lista de diccionarios de tareas.
        indice (int): Posición actual que se está evaluando en la recursión (por defecto 0).

    Retorna:
        int: Cantidad total de tareas con estado 'completada' igual a False.
    """
    # CASO BASE: Si el índice alcanza el tamaño total de la lista, detenemos la recursión
    if indice == len(lista_tareas):
        return 0

    # CASO RECURSIVO: Evaluamos la tarea en la posición actual
    if not lista_tareas[indice]["completada"]:
        # Si está pendiente (False), sumamos 1 y avanzamos al siguiente índice
        return 1 + contar_tareas_pendientes(lista_tareas, indice + 1)
    else:
        # Si ya está completada (True), no sumamos nada y avanzamos al siguiente índice
        return contar_tareas_pendientes(lista_tareas, indice + 1)


# ==========================================
# FLUJO PRINCIPAL DEL PROGRAMA
# ==========================================
def ejecutar_programa():
    """
    Controla el ciclo principal y el menú interactivo de consola.
    """
    # Inicialización de datos mediante la función modular
    mis_tareas = obtener_tareas()

    while True:
        print("\n=== GESTOR DE TAREAS PENDIENTES ===")
        print("1. Ver tareas")
        print("2. Agregar tarea")
        print("3. Marcar tarea como completada")
        print("4. Mostrar total de tareas pendientes")
        print("5. Salir")

        opcion = input("Seleccione una opción (1-5): ")

        if opcion == "1":
            mostrar_tareas(mis_tareas)

        elif opcion == "2":
            desc = input("Ingrese la descripción de la nueva tarea: ").strip()
            if desc:
                mis_tareas = agregar_tarea(mis_tareas, desc)
            else:
                print("Error: La descripción no puede estar vacía.")

        elif opcion == "3":
            mostrar_tareas(mis_tareas)
            try:
                num_tarea = int(input("Ingrese el número de la tarea a completar: "))
                marcar_completada(mis_tareas, num_tarea)
            except ValueError:
                print("Error: Debe ingresar un número entero válido.")

        elif opcion == "4":
            total_pendientes = contar_tareas_pendientes(mis_tareas)
            print(f"\n-> Tienes un total de {total_pendientes} tarea(s) pendiente(s).")

        elif opcion == "5":
            print("Saliendo del gestor de tareas. ¡Hasta luego!")
            break

        else:
            print("Opción no válida. Por favor, elija un número del 1 al 5.")


if __name__ == "__main__":
    ejecutar_programa()

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: