# =============================================================================
# BUCLES WHILE EN PYTHON
# =============================================================================
# Un bucle "while" repite un bloque de código MIENTRAS se cumpla una condición.
# Es ideal cuando no sabemos de antemano cuántas veces necesitamos repetir algo.
#
# Estructura básica:
#
# while condición:
# instrucción 1 ← estas líneas se repiten mientras la condición sea True
# instrucción 2
#
# ¡CUIDADO! Si la condición nunca se vuelve False, el bucle no termina nunca
# (bucle infinito). Siempre hay que asegurarse de que algo dentro del bucle
# hace que la condición cambie.
#
# En este archivo veremos 6 ejemplos prácticos:
# 1. Calcular el factorial de un número
# 2. Repetir algo hasta que el usuario decida parar
# 3. Tabla de multiplicar del 7
# 4. Sumar los números del 0 al 100
# 5. Saludar a varios usuarios hasta que no introduzcan nombre
# 6. Acumular números introducidos por el usuario
# =============================================================================
# =============================================================================
# EJEMPLO 1: CÁLCULO DEL FACTORIAL CON UN BUCLE WHILE
# =============================================================================
# El factorial de un número n (escrito n!) es la multiplicación de todos los
# números enteros desde 1 hasta n.
# Ejemplo: 5! = 1 × 2 × 3 × 4 × 5 = 120
#
# Interacción esperada:
# Introduce un numero: 5
# El factorial de 5 es 120
# =============================================================================
numero = int(input("Introduce un numero: "))
# input() siempre devuelve texto (string). int() lo convierte a número entero.
# Si el usuario escribe "5", sin int() tendríamos la cadena "5", no el número 5.
# PRUEBA: quita el int() y observa el error que aparece al hacer cálculos.
factorial = 1
# Inicializamos factorial a 1, no a 0.
# Si lo inicializáramos a 0, cualquier multiplicación daría 0 (0 × lo que sea = 0).
# Esta variable irá acumulando el resultado de las multiplicaciones.
contador = 1
# El contador empieza en 1 porque la multiplicación parte de 1.
# Esta variable controla el bucle: irá de 1 hasta "numero".
while contador <= numero:
# La condición comprueba si contador todavía no ha superado "numero".
# Cuando contador > numero, el bucle se detiene.
# Ejemplo con numero=4: el bucle se ejecuta para contador = 1, 2, 3, 4
factorial = factorial * contador
# Multiplicamos el factorial acumulado por el contador actual.
# Es lo mismo que: factorial *= contador (forma abreviada)
# Paso a paso con numero=4:
# Vuelta 1: factorial = 1 × 1 = 1
# Vuelta 2: factorial = 1 × 2 = 2
# Vuelta 3: factorial = 2 × 3 = 6
# Vuelta 4: factorial = 6 × 4 = 24 → El factorial de 4 es 24 ✓
contador = contador + 1
# Incrementamos el contador para avanzar al siguiente número.
# Es lo mismo que: contador += 1 (forma abreviada)
# SIN esta línea, contador siempre valdría 1 y el bucle nunca terminaría.
print(f"El factorial de {numero} es {factorial}")
# Las f-strings permiten insertar variables dentro del texto con {}.
# ALTERNATIVA sin f-string: print("El factorial de", numero, "es", factorial)
# ALTERNATIVA avanzada: Python tiene math.factorial(n) que hace esto automáticamente:
# import math
# print(math.factorial(5)) → 120
# =============================================================================
# EJEMPLO 2: BUCLE CONTROLADO POR EL USUARIO (SEGUIR / PARAR)
# =============================================================================
# Este ejemplo muestra cómo dejar que el USUARIO decida cuándo parar el bucle.
# Contamos cuántas veces decide continuar.
#
# Interacción esperada:
# 0
# ¿Deseas seguir? (Sí/No): Sí
# 1
# ¿Deseas seguir? (Sí/No): Sí
# 2
# ¿Deseas seguir? (Sí/No): No
# =============================================================================
seguir = "Sí"
# Inicializamos la variable centinela con "Sí" para que el bucle empiece.
# Una variable "centinela" es aquella cuyo valor controla si el bucle continúa.
# IMPORTANTE: debe coincidir exactamente con la condición del while.
contador = 0
# Empezamos el contador en 0 y lo iremos mostrando en cada vuelta.
while seguir == "Sí":
# El bucle continúa MIENTRAS el usuario escriba exactamente "Sí".
# Si escribe "si", "SI", "sí" con minúscula... el bucle se detiene.
# ALTERNATIVA más flexible: while seguir.lower() == "sí":
# Con .lower() convertimos a minúsculas y aceptamos "Sí", "SÍ", "sí"...
print(contador)
# Mostramos el valor actual del contador antes de preguntar.
seguir = input("¿Desas seguir? (Sí/No): ")
# Aquí el usuario puede escribir "Sí" o "No".
# Este input SOBREESCRIBE el valor anterior de "seguir".
# Si escribe "No" (o cualquier cosa que no sea "Sí"), el bucle termina.
contador = contador + 1
# Incrementamos el contador en cada vuelta.
# =============================================================================
# EJEMPLO 3: TABLA DE MULTIPLICAR DEL 7
# =============================================================================
# Recorremos los números del 1 al 10 y multiplicamos cada uno por 7.
#
# Resultado esperado:
# 1 x 7 = 7
# 2 x 7 = 14
# 3 x 7 = 21
# ...
# 10 x 7 = 70
# =============================================================================
numero = 1
# Reutilizamos el nombre "numero" (la variable del ejemplo anterior ya no se usa).
# El número empieza en 1 porque las tablas de multiplicar van del 1 al 10.
while numero <= 10:
# El bucle se ejecuta mientras numero sea menor o igual a 10.
# Se ejecutará exactamente 10 veces: para 1, 2, 3, ..., 10.
print(f"{numero} x 7 = {numero * 7}")
# Mostramos la operación completa y su resultado.
# numero * 7 se calcula directamente dentro de la f-string.
# ALTERNATIVA: resultado = numero * 7 y luego print(f"{numero} x 7 = {resultado}")
numero = numero + 1
# Avanzamos al siguiente número.
# Sin esta línea: número siempre sería 1 → bucle infinito imprimiendo "1 x 7 = 7"
# ALTERNATIVA con for (más natural para recorrer rangos conocidos):
# for numero in range(1, 11): # range(1,11) genera: 1, 2, 3, ..., 10
# print(f"{numero} x 7 = {numero * 7}")
#
# RETO: modifica el código para que pregunte al usuario qué tabla quiere ver.
# =============================================================================
# EJEMPLO 4: SUMAR TODOS LOS NÚMEROS DEL 0 AL 100
# =============================================================================
# Acumulamos la suma de 0 + 1 + 2 + 3 + ... + 100 = 5050
#
# Resultado esperado:
# 5050
# =============================================================================
contador = 0
# El contador empieza en 0 porque queremos sumar desde 0.
suma = 0
# La variable acumuladora también empieza en 0.
# Irá almacenando la suma parcial en cada vuelta.
# NUNCA inicialices una suma acumuladora a otro valor que no sea 0,
# ya que añadiría un "extra" a todos los cálculos.
while contador <= 100:
# El bucle recorre todos los números de 0 a 100, ambos incluidos.
suma = suma + contador
# Añadimos el valor actual del contador a la suma acumulada.
# Es lo mismo que: suma += contador
# Paso a paso:
# Vuelta 0: suma = 0 + 0 = 0
# Vuelta 1: suma = 0 + 1 = 1
# Vuelta 2: suma = 1 + 2 = 3
# Vuelta 3: suma = 3 + 3 = 6
# ... y así hasta 100
contador = contador + 1
# Avanzamos al siguiente número.
print(suma)
# Imprime 5050. Existe una fórmula matemática directa: n*(n+1)/2 → 100*101/2 = 5050
# ALTERNATIVA con for y sum():
# print(sum(range(101))) → 5050 (range(101) genera del 0 al 100)
# =============================================================================
# EJEMPLO 5: SALUDAR USUARIOS HASTA QUE NO SE INTRODUZCA NOMBRE
# =============================================================================
# El bucle se repite mientras el usuario introduzca un nombre.
# Si pulsa Enter sin escribir nada, el programa termina.
#
# Interacción esperada:
# Dime tu nombre (pulsa enter sin poner nada para salir)
# Tu nombre: Ana
# Hola Ana
# Tu nombre: Luis
# Hola Luis
# Tu nombre: ← el usuario pulsa Enter sin escribir
# (el programa termina)
# =============================================================================
print("Dime tu nombre (pulsa enter sin poner nada para salir)")
# Mensaje informativo para que el usuario sepa cómo funciona el programa.
nombre = input("Tu nombre: ")
# Pedimos el nombre ANTES del bucle para poder comprobar la condición.
# Si lo pidiéramos dentro del bucle, no podríamos comprobar el primer valor.
# Si el usuario pulsa Enter sin escribir nada, nombre será "" (cadena vacía).
while nombre != "":
# El bucle continúa MIENTRAS nombre sea diferente de "" (cadena vacía).
# "" es una cadena sin ningún carácter, lo que ocurre al pulsar Enter vacío.
# ALTERNATIVA equivalente: while nombre: (una cadena vacía equivale a False)
print("Hola", nombre)
# Saludamos al usuario. También podría ser: print(f"Hola {nombre}")
nombre = input("Tu nombre: ")
# Volvemos a pedir el nombre al final del bucle para actualizar la condición.
# Este patrón (pedir antes del while y al final del bucle) es muy común
# cuando la condición depende de un input del usuario.
# =============================================================================
# EJEMPLO 6A: SUMAR LOS N PRIMEROS NÚMEROS (EL USUARIO ELIGE HASTA DÓNDE)
# =============================================================================
# El usuario indica un límite y sumamos todos los números desde 1 hasta ese límite.
#
# Interacción esperada:
# Ingrese un numero hasta el que quiere sumar: 10
# La suma de los 10 primeros números es: 55
# =============================================================================
limite = int(input("Ingrese un numero hasta el que quiere sumar: "))
# El usuario decide hasta qué número se suma.
# int() es necesario para poder usar el valor como límite numérico.
suma = 0
# Acumulador de la suma, siempre inicializado a 0.
contador = 1
# Empezamos en 1 porque queremos sumar los números POSITIVOS hasta el límite.
# Si el límite fuera 5: sumaríamos 1+2+3+4+5 = 15.
while contador <= limite:
# El bucle avanza mientras el contador no supere el límite elegido.
suma = suma + contador
# Acumulamos el valor actual del contador en la suma.
contador = contador + 1
# Avanzamos al siguiente número.
print(f"La suma de los {limite} primeros números es: {suma}")
# Mostramos el resultado final con el límite y la suma obtenida.
# RETO: prueba con limite=100, ¿obtienes 5050 igual que en el ejemplo 4?
# =============================================================================
# EJEMPLO 6B: SUMAR NÚMEROS INTRODUCIDOS POR EL USUARIO (0 PARA TERMINAR)
# =============================================================================
# El usuario va introduciendo números uno a uno y los vamos sumando.
# Cuando introduce 0, el bucle termina y mostramos la suma total.
# El 0 es el "número centinela": su único papel es indicar que queremos parar.
#
# Interacción esperada:
# ingrese un numero: 5
# ingrese un numero: 3
# ingrese un numero: 10
# ingrese un numero: 0
# 18 ← 5 + 3 + 10 (el 0 no se suma)
# =============================================================================
numero = int(input("ingrese un numero: "))
# Pedimos el primer número antes del bucle para poder evaluarlo en la condición.
# Si lo pidiéramos dentro, no podríamos comprobar si es 0 antes de la primera vuelta.
suma = 0
# Acumulador que irá guardando la suma de todos los números introducidos.
while numero != 0:
# El bucle continúa MIENTRAS el número introducido sea distinto de 0.
# En cuanto el usuario escriba 0, el bucle termina SIN sumar ese 0.
# Por eso el 0 no aparece en la suma: la condición se comprueba antes de sumar.
suma = suma + numero
# Añadimos el número actual a la suma acumulada.
# Solo llegamos aquí si numero != 0, así que el 0 nunca se suma.
numero = int(input("ingrese un numero: "))
# Pedimos el siguiente número. Si el usuario introduce 0 aquí,
# la próxima comprobación del while será False y el bucle terminará.
print(suma)
# Mostramos la suma total de todos los números introducidos (sin contar el 0).
# MEJORA: print(f"La suma total es: {suma}")
#
# RETO: modifica el programa para que también muestre cuántos números
# introdujo el usuario y cuál es la media.