Bucles en Python — ejercicios con FizzBuzz, una inversión que crece, primos y un plan de ahorro (y el break que solo salía de la bandeja)

En un simulacro de FP1 me tocó un ejercicio de buscar: «recorre las bandejas del mostrador y di dónde está el primer croissant de chocolate». Dos bucles, uno dentro de otro, y un break al encontrarlo. Lo entregué tan tranquilo. Al corregirlo, mi programa había encontrado dos «primeros» croissants. El break funcionaba, sí… pero solo sacaba del bucle de la bandeja; el de fuera seguía tan feliz con la siguiente. Lo tienes en «¿Qué falla aquí?», con el arreglo y un dibujo de qué piezas mira cada versión.

Ya tienes la teoría y la práctica de bucles en Python. Ahora te toca a ti: cuatro ejercicios en tres niveles (básico, intermedio y desafío final), tres fragmentos con un fallo escondido, las soluciones comentadas línea a línea y un chuletario para tenerlo todo a mano. Todos los programas usan datos fijos, sin input(), y las salidas que ves son las de su ejecución real.

Cómo usar este artículo

  1. Lee el enunciado y la salida esperada, y escribe tu solución en VS Code sin mirar nada más.
  2. Si llevas más de 10 minutos atascado, abre la pista (y solo la pista).
  3. Compara tu salida con la esperada carácter a carácter: un número de más o de menos suele ser un range mal cerrado.
  4. Lee la solución comentada aunque te haya salido bien: muchas veces hay una decisión que no habías pensado.

Nivel básico

Ejercicio 1: FizzBuzz

FizzBuzz es probablemente el ejercicio de programación más famoso del mundo; se usa incluso como filtro en entrevistas de trabajo. Escribe un programa que recorra los números del 1 al 100 y, para cada uno:

  • si es divisible por 3 y por 5, escriba FizzBuzz;
  • si solo es divisible por 3, Fizz;
  • si solo es divisible por 5, Buzz;
  • si no, el propio número.

Para que la salida no ocupe 100 líneas, escribe los resultados separados por espacios y salta de línea cada 10 números. Salida esperada:

1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 
11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz 
Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 
31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 
41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz 
Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 
61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 
71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz 
Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 
91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz 

for i in range(1, 101): sabes que son 100 números (y el fin no entra). El truco está en el orden de los if/elif: el caso de «divisible por 3 y por 5» tiene que ir el primero. Para no saltar de línea en cada número, print(texto, end=" "); para saltar cada 10, un if i % 10 == 0: print().

Ejercicio 2: Calculadora de interés compuesto

Con el bote de la cafetería se han juntado 1.000 € y se meten en una cuenta al 5 % anual durante 5 años. Con interés compuesto, cada año los intereses se suman al capital y al año siguiente también generan intereses: capital = capital × (1 + interés / 100). Escribe un programa que muestre el capital al final de cada año (redondeado a 2 decimales) con lo que se ha ganado ese año, y al final el capital, el total ganado y la rentabilidad en porcentaje. Salida esperada:

--- Evolución de la inversión ---
Año 1: 1050.00 € (+50.00 €)
Año 2: 1102.50 € (+52.50 €)
Año 3: 1157.62 € (+55.12 €)
Año 4: 1215.50 € (+57.88 €)
Año 5: 1276.28 € (+60.78 €)
Capital final: 1276.28 €
Total ganado: 276.28 €
Rentabilidad: 27.63 %

for año in range(1, años + 1), porque sabes cuántos años son. Para la ganancia de cada año necesitas el capital de antes de actualizarlo: guárdalo en otra variable al principio de la vuelta. Redondea con round(…, 2) en cada año, como haría un banco.

Nivel intermedio

Ejercicio 3: Generador de números primos

Un número es primo si solo es divisible por 1 y por sí mismo. Escribe un programa que encuentre todos los primos del 2 al 30, los muestre en una línea, diga cuántos hay y cuente cuántas divisiones (%) ha tenido que hacer en total. Salida esperada:

Primos hasta 30: 2 3 5 7 11 13 17 19 23 29 
Total: 10 primos
Divisiones hechas: 45

Dos bucles anidados. El de fuera recorre los candidatos del 2 al 30; el de dentro prueba divisores. Usa una bandera es_primo = True que pase a False si encuentras un divisor, y un break en ese momento (ya no hace falta seguir con ese número). Basta con probar divisores hasta la raíz cuadrada: range(2, int(numero ** 0.5) + 1). Si te salen más de 45 divisiones, te falta el break o el límite de la raíz.

Desafío final

Ejercicio 4: Simulador de ahorro mensual

La cafetería quiere una cafetera nueva de 10.000 €. Cada mes se ahorran 300 € en una cuenta al 4 % anual. Cada mes, primero se ingresan los 300 € y después se aplica el interés mensual (el anual entre 12), redondeando el saldo a 2 decimales. ¿Cuántos meses hacen falta para llegar al objetivo? Muestra el saldo de los meses del tercer año en adelante (a partir del 25) hasta el mes en que se alcanza, el tiempo en años y meses, lo ahorrado, lo aportado y los intereses. Y si el ahorro mensual fuera 0 o negativo, el programa tiene que avisar en lugar de quedarse colgado. Salida esperada:

Mes 25: 7833.84 €
Mes 26: 8160.95 €
Mes 27: 8489.15 €
Mes 28: 8818.45 €
Mes 29: 9148.84 €
Mes 30: 9480.34 €
Mes 31: 9812.94 €
Mes 32: 10146.65 €
Objetivo alcanzado en 32 meses (2 años y 8 meses)
Ahorrado: 10146.65 € | aportado: 9600.00 €
Intereses: 546.65 €

No sabes cuántos meses harán falta, así que while balance < objetivo:. El interés mensual es 4 / 12 / 100. Para los años y los meses que sobran, meses // 12 y meses % 12 (los viste en operadores). Y piensa qué pasaría con ahorro_mensual = 0: el saldo nunca crecería y el while no acabaría nunca, así que compruébalo con un if antes del bucle.

¿Qué falla aquí?

Tres fragmentos cortos, cada uno con un fallo típico de bucles. Antes de leer la explicación, predice qué imprimen.

Fragmento 1: los días que no cuadran

Queremos sumar las ventas de los días 1 a 10, a 100 € por día:

# Quiero sumar las ventas de los días 1 a 10 (100 € al día)
total = 0
for dia in range(1, 10):
    total += 100
print("Último día sumado:", dia)
print("Total:", total, "€")

¿Qué imprime? Piénsalo antes de seguir.

Salida real:

Último día sumado: 9
Total: 900 €

Faltan 100 €: el día 10 no se ha sumado. range(1, 10) genera del 1 al 9, porque el fin nunca entra. Por eso dia termina valiendo 9 y el total es 9 × 100 = 900.

El «error de uno». Si quieres llegar hasta N, el fin de range es N + 1.

El arreglo es cambiar el 10 por un 11:

# Arreglado: el fin de range no entra, así que para llegar al 10 hay que poner 11
total = 0
for dia in range(1, 11):
    total += 100
print("Último día sumado:", dia)
print("Total:", total, "€")

Salida:

Último día sumado: 10
Total: 1000 €

Para comprobar un range sin ejecutar el bucle entero, imprime list(range(1, 10)) o len(range(1, 10)). Si len no da los días que esperas, el fallo está ahí.

Fragmento 2: el primer croissant de chocolate

Este es el de mi anécdota. Las bandejas son textos: cada letra es una pieza (N normal, C chocolate). Queremos el primer croissant de chocolate y parar:

# Busco el PRIMER croissant de chocolate (C) y quiero parar en cuanto lo encuentre
bandejas = ["NNC", "CNC", "NNN"]  # N = normal, C = chocolate
num = 0
for bandeja in bandejas:
    num += 1
    hueco = 0
    for pieza in bandeja:         # un for también recorre un texto, letra a letra
        hueco += 1
        if pieza == "C":
            print(f"Chocolate: bandeja {num}, hueco {hueco}")
            break
print("Búsqueda terminada")

¿Cuántas líneas de «Chocolate» saldrán?

Salida real:

Chocolate: bandeja 1, hueco 3
Chocolate: bandeja 2, hueco 1
Búsqueda terminada

Dos. El break saca del bucle de las piezas (for pieza in bandeja), pero no del de las bandejas: el de fuera da su siguiente vuelta, entra en la bandeja 2 y vuelve a encontrar un chocolate. break solo termina el bucle más interno en el que está. El dibujo compara qué piezas se llegan a mirar con cada versión:

Qué piezas mira cada versiónDos paneles con tres bandejas de tres piezas (C = chocolate, N = normal). Con solo break se miran las tres piezas de la bandeja 1, la primera de la 2 y las tres de la 3, y se encuentran dos chocolates. Con la bandera solo se mira la bandeja 1.Solo breakbandeja 1NNCbreakbandeja 2CbreakNCbandeja 3NNN2 chocolates: el bucle de fuera siguebreak + banderabandeja 1NNCbreakbandeja 2CNCno se mirabandeja 3NNNno se mira1 chocolate: la bandera para el de fuera
break sale únicamente del bucle en el que está; para parar también el de fuera hace falta otra señal.

Esperar que un break dentro de dos bucles los termine los dos. Solo termina el de dentro.

El arreglo: una bandera que el bucle de dentro pone a True y que el de fuera mira después de cada bandeja:

# Arreglado: una bandera avisa al bucle de fuera de que ya hemos terminado
bandejas = ["NNC", "CNC", "NNN"]  # N = normal, C = chocolate
num = 0
encontrado = False
for bandeja in bandejas:
    num += 1
    hueco = 0
    for pieza in bandeja:
        hueco += 1
        if pieza == "C":
            print(f"Chocolate: bandeja {num}, hueco {hueco}")
            encontrado = True
            break                 # sale del bucle de las piezas...
    if encontrado:
        break                     # ...y este, del de las bandejas
print("Búsqueda terminada")

Salida:

Chocolate: bandeja 1, hueco 3
Búsqueda terminada

Cuando sepas funciones (el siguiente tema), hay una forma aún más limpia: meter la búsqueda en una función y usar return, que sale de todos los bucles de golpe.

Fragmento 3: el total que se olvida

Sumar los tickets de la mañana:

# Sumar los tickets de la mañana
tickets = [3.50, 1.20, 4.80]
for ticket in tickets:
    total = 0
    total += ticket
print(f"Total: {total:.2f} €")

¿Cuánto da el total?

Salida real:

Total: 4.80 €

4,80 €: solo el último ticket. total = 0 está dentro del bucle, así que en cada vuelta se reinicia antes de sumar. Al final de la vuelta 3, total vale 0 + 4,80. Lo que se había sumado en las vueltas 1 y 2 se ha perdido.

Inicializar el acumulador dentro del bucle. Va antes, a la altura del for.

# Arreglado: el acumulador se crea UNA vez, antes del bucle
tickets = [3.50, 1.20, 4.80]
total = 0
for ticket in tickets:
    total += ticket
print(f"Total: {total:.2f} €")

Salida:

Total: 9.50 €

Comprobación: 3,50 + 1,20 + 4,80 = 9,50 €.

Soluciones comentadas

Solución del ejercicio 1: FizzBuzz

# Nivel básico · Ejercicio 1: FizzBuzz del 1 al 100, diez por línea
for i in range(1, 101):           # 101 para que el 100 entre
    if i % 3 == 0 and i % 5 == 0: # PRIMERO el caso doble: si no, el 15 se quedaría en "Fizz"
        texto = "FizzBuzz"
    elif i % 3 == 0:
        texto = "Fizz"
    elif i % 5 == 0:
        texto = "Buzz"
    else:
        texto = str(i)            # el número tal cual, como texto
    print(texto, end=" ")         # todo en la misma línea...
    if i % 10 == 0:
        print()                   # ...hasta llegar a un múltiplo de 10

Por qué está hecho así:

  • El orden de las condiciones. El 15 es divisible por 3 y por 5. Si la primera pregunta fuera i % 3 == 0, el 15 entraría ahí, escribiría «Fizz» y los elif de debajo ni se mirarían. Por eso el caso doble va primero. Otra forma equivalente: i % 15 == 0 (divisible por 3 y por 5 es lo mismo que divisible por 15).
  • Una variable texto y un solo print. Cada rama solo decide qué texto toca; el print está una vez, al final. Si mañana cambias el formato, lo cambias en un sitio.
  • str(i). En las otras ramas texto es un texto; así las cuatro ramas dejan el mismo tipo en la variable.
  • El salto de línea. end=" " mantiene todo en la misma línea, y if i % 10 == 0: print() salta en el 10, el 20… El print() vacío solo imprime el salto.

Comprobación de la primera línea: 3 y 6 y 9 → Fizz; 5 y 10 → Buzz; el resto, números. En la segunda línea, el 15 → FizzBuzz.

Solución del ejercicio 2: Interés compuesto

# Nivel básico · Ejercicio 2: interés compuesto año a año
capital_inicial = 1000.0
interes = 5.0                     # % anual
años = 5

capital = capital_inicial         # el capital que va creciendo (el inicial no se toca)
print("--- Evolución de la inversión ---")
for año in range(1, años + 1):    # sabemos cuántos años: for
    anterior = capital            # se guarda ANTES de actualizar, para la ganancia del año
    capital = round(capital * (1 + interes / 100), 2)
    ganancia = round(capital - anterior, 2)
    print(f"Año {año}: {capital:.2f} € (+{ganancia:.2f} €)")

total = round(capital - capital_inicial, 2)
print(f"Capital final: {capital:.2f} €")
print(f"Total ganado: {total:.2f} €")
print(f"Rentabilidad: {total / capital_inicial * 100:.2f} %")

Por qué está hecho así:

  • for y no while: sabemos que son 5 años.
  • capital y capital_inicial separados: capital va cambiando, pero al final necesitamos el inicial para calcular lo ganado y la rentabilidad.
  • anterior se guarda al principio de la vuelta: después de capital = … el valor viejo ya no existe. Sin anterior, no podríamos saber cuánto se ganó ese año.
  • round(…, 2) en cada año, como haría un banco: el siguiente año calcula sobre el capital ya redondeado.

Traza vuelta a vuelta:

Añoanteriorcapital × 1,05capital (redondeado)ganancia
11000.001050.01050.0050.00
21050.001102.51102.5052.50
31102.501157.6251157.6255.12
41157.621215.5011215.5057.88
51215.501276.2751276.2860.78

¿Por qué el año 3 se redondea a 1157,62 y no a 1157,63? Porque 1157,625 no se puede guardar exacto en un float: en memoria es algo como 1157,62499999…, y round lo redondea hacia abajo. Es el mismo problema de los floats que vimos en variables y tipos de datos. La rentabilidad: 276,28 / 1000 × 100 = 27,63 %.

Si quieres céntimos exactos (como en el cambio de la caja de la teoría), trabaja en céntimos enteros y divide entre 100 solo al mostrar.

Solución del ejercicio 3: Números primos

# Nivel intermedio · Ejercicio 3: números primos hasta n
n = 30
primos = []
comprobaciones = 0                # cuántas divisiones hace en total

for numero in range(2, n + 1):    # bucle exterior: cada candidato
    es_primo = True               # inocente hasta que se demuestre lo contrario
    for divisor in range(2, int(numero ** 0.5) + 1):   # basta con llegar a la raíz
        comprobaciones += 1
        if numero % divisor == 0:
            es_primo = False
            break                 # ya hay un divisor: no hace falta seguir con ESTE número
    if es_primo:
        primos.append(numero)

texto = ""
for p in primos:
    texto += str(p) + " "
print(f"Primos hasta {n}: {texto}")
print(f"Total: {len(primos)} primos")
print(f"Divisiones hechas: {comprobaciones}")

Por qué está hecho así:

  • La bandera es_primo se pone a True al principio de cada vuelta de fuera. Cada candidato empieza «inocente». Si la pusieras antes del bucle de fuera, en cuanto un número no fuera primo (el 4), todos los demás quedarían marcados como no primos.
  • El break corta el bucle de los divisores en cuanto aparece uno: el 30 ya se sabe que no es primo al dividir entre 2, no hace falta probar 3, 4 y 5. Por eso hay 45 divisiones y no muchas más.
  • Hasta la raíz cuadrada: si un número tiene un divisor mayor que su raíz, también tiene uno menor (por ejemplo, 28 = 2 × 14), y ese ya lo habríamos encontrado. int(numero ** 0.5) + 1 es el + 1 de siempre del range.
  • Para 2 y 3, el bucle de dentro está vacío (range(2, 2)): no da vueltas, la bandera sigue en True y se dan como primos, que es correcto.

Así se ve dónde actúa el break en cada número:

Primos hasta 30 y dónde actúa el breakLos números del 2 al 30 en tres filas. Los primos 2, 3, 5, 7, 11, 13, 17, 19, 23 y 29 van en violeta. Cada número compuesto lleva su primer divisor, que es donde el bucle interior hace break.Del 2 al 30: violeta = primo · «÷d» = primer divisor, ahí salta el break234÷256÷278÷29÷310÷21112÷21314÷215÷316÷21718÷21920÷221÷322÷22324÷225÷526÷227÷328÷22930÷2
Para cada número compuesto, el bucle interior se para en cuanto encuentra su primer divisor.

Zoom a los dos bucles:

for numero in range(2, n + 1):    # bucle exterior: cada candidato
    es_primo = True               # inocente hasta que se demuestre lo contrario
    for divisor in range(2, int(numero ** 0.5) + 1):   # basta con llegar a la raíz
        comprobaciones += 1
        if numero % divisor == 0:
            es_primo = False
            break                 # ya hay un divisor: no hace falta seguir con ESTE número
    if es_primo:
        primos.append(numero)
numerodivisores probados¿break?es_primo
2, 3ninguno (rango vacío)—True
42sí, en el 2False
92, 3sí, en el 3False
252, 3, 4, 5sí, en el 5False
292, 3, 4, 5noTrue

Solución del ejercicio 4: Simulador de ahorro

# Desafío final · Ejercicio 4: ¿cuántos meses hasta llegar al objetivo?
objetivo = 10000.0
ahorro_mensual = 300.0
interes_anual = 4.0               # %

if ahorro_mensual <= 0:           # con 0 € al mes el while no acabaría nunca
    print("Error: el ahorro mensual tiene que ser mayor que 0")
else:
    interes_mensual = interes_anual / 12 / 100
    balance = 0.0
    mes = 0
    aportado = 0.0
    while balance < objetivo:     # no sabemos cuántos meses: while
        mes += 1
        balance += ahorro_mensual                          # 1.º se ingresa el mes
        balance = round(balance * (1 + interes_mensual), 2) # 2.º se aplica el interés
        aportado += ahorro_mensual
        if mes > 24:              # solo enseñamos los últimos meses
            print(f"Mes {mes}: {balance:.2f} €")

    años = mes // 12
    resto = mes % 12
    print(f"Objetivo alcanzado en {mes} meses ({años} años y {resto} meses)")
    print(f"Ahorrado: {balance:.2f} € | aportado: {aportado:.2f} €")
    print(f"Intereses: {balance - aportado:.2f} €")

Por qué está hecho así:

  • El if antes del while: con ahorro_mensual <= 0 el saldo nunca crecería y balance < objetivo sería True para siempre. Se comprueba antes de entrar, no dentro.
  • while y no for: no sabemos cuántos meses hacen falta; eso es justo lo que queremos averiguar.
  • El orden dentro de la vuelta: primero se ingresa y luego se aplica el interés, como dice el enunciado. Al revés saldría otro número de meses (los 300 € del mes no generarían interés ese mes).
  • mes empieza en 0 y se suma al principio de la vuelta: así, al salir del bucle, mes vale exactamente el número de meses que se han simulado.
  • if mes > 24 dentro del bucle: decide qué meses se imprimen sin necesidad de guardar el historial.

Zoom al bucle:

while balance < objetivo:     # no sabemos cuántos meses: while
    mes += 1
    balance += ahorro_mensual                          # 1.º se ingresa el mes
    balance = round(balance * (1 + interes_mensual), 2) # 2.º se aplica el interés
    aportado += ahorro_mensual
    if mes > 24:              # solo enseñamos los últimos meses
        print(f"Mes {mes}: {balance:.2f} €")

Comprobación: 32 meses son 32 // 12 = 2 años y 32 % 12 = 8 meses. Aportado: 32 × 300 = 9.600 €. Intereses: 10.146,65 − 9.600 = 546,65 €. En el mes 31 el saldo (9.812,94 €) todavía no llega a 10.000, así que el bucle da una vuelta más; en el 32 lo supera y la condición 10146.65 < 10000.0 ya es False.


Cuestionario tipo examen

Ahora ponte a prueba como en el examen. Los cuestionarios de FP1 son así: 15 preguntas en 20 minutos (16 en 30 en el de Secuencias), casi todas de respuesta única (cada fallo resta un tercio de lo que vale la pregunta) y muchas de «¿qué imprime este código?», con algún hueco, relacionar o verdadero o falso. Aquí tienes 13 preguntas originales sobre bucles. Contesta sin ejecutar nada, pulsa Comprobar y lee la explicación de cada una. Estas preguntas son también el banco del simulacro de teoría de FP1, que las mezclará con las de los demás temas.

Pregunta 1Respuesta corta

¿Qué valor tiene x al terminar? Escribe solo el número.

x = 0
i = 1
while i < 5:
    x += i
    i += 1
print(x)
Solución

Respuesta: 10

El bucle suma i mientras i < 5: 1 + 2 + 3 + 4 = 10. Cuando i llega a 5, la condición es falsa y el bucle termina sin sumarlo.

Pregunta 2Única

¿Qué números genera range(2, 10, 3)?

  1. 2, 5 y 8
  2. 2, 5, 8 y 11
  3. 2, 3, 4, 5, 6, 7, 8 y 9
  4. 3, 6 y 9
Solución

Respuesta: 2, 5 y 8

range(inicio, fin, paso): empieza en inicio, suma paso cada vez y no incluye fin. Por eso range(5) da 0, 1, 2, 3 y 4.

Pregunta 3Respuesta corta

¿Cuántas veces se imprime hola? Escribe solo el número.

for i in range(3):
    for j in range(4):
        print("hola")
Solución

Respuesta: 12

Por cada una de las 3 vueltas del bucle de fuera, el de dentro da 4 vueltas: 3 × 4 = 12. En los bucles anidados, las vueltas se multiplican.

Pregunta 4Única

¿Qué imprime este código?

for n in range(1, 10):
    if n % 4 == 0:
        break
    print(n, end=" ")
  1. 1 2 3
  2. 1 2 3 4
  3. 1 2 3 5 6 7 9
  4. 4 8
Solución

Respuesta: 1 2 3

break termina el bucle entero en cuanto se ejecuta. continue, en cambio, se salta lo que queda de esa vuelta y sigue con la siguiente.

Pregunta 5Respuesta corta

¿Qué imprime este programa? Escribe la salida exacta.

s = 0
for n in range(1, 8):
    if n % 2 == 0:
        continue
    s += n
print(s)
Solución

Respuesta: 16

continue se salta los pares, así que solo se suman los impares de 1 a 7: 1 + 3 + 5 + 7 = 16.

Pregunta 6Única

¿Cuándo es mejor un while que un for?

  1. Cuando no sabes de antemano cuántas vueltas hará el bucle
  2. Cuando quieres recorrer una lista
  3. Nunca: el while es una forma antigua del for
  4. Cuando el bucle tiene un número fijo de vueltas
Solución

Respuesta: Cuando no sabes de antemano cuántas vueltas hará el bucle

for = «haz esto para cada elemento» (o un número fijo de veces). while = «repite mientras se cumpla la condición». Con while, acuérdate de cambiar algo dentro del bucle o no acabará nunca.

Pregunta 7Única

¿Qué le pasa a este programa?

i = 10
while i > 0:
    print(i)
i -= 1
  1. No termina nunca: i -= 1 está fuera del bucle y i siempre vale 10
  2. Imprime de 10 a 1
  3. Imprime solo el 10
  4. Da un error de sintaxis
Solución

Respuesta: No termina nunca: i -= 1 está fuera del bucle y i siempre vale 10

Es un bucle infinito: la condición i > 0 nunca deja de cumplirse porque i no cambia dentro del bucle. En la terminal se corta con Ctrl + C.

Pregunta 8Verdadero o falso

Indica si es verdadero o falso:

  1. for letra in 'hola': da 4 vueltas.
  2. range(5) incluye el 5.
  3. Un while cuya condición es falsa desde el principio no da ninguna vuelta.
  4. break dentro de dos bucles anidados sale de los dos.
Solución
  • V — for letra in 'hola': da 4 vueltas.
  • F — range(5) incluye el 5.
  • V — Un while cuya condición es falsa desde el principio no da ninguna vuelta.
  • F — break dentro de dos bucles anidados sale de los dos.

Un for recorre cualquier secuencia, también un texto (una vuelta por carácter). range(5) va de 0 a 4. Y break solo sale del bucle en el que está: el de fuera sigue.

Pregunta 9Única

¿Qué imprime este código?

n = 1
while n < 100:
    n = n * 3
print(n)
  1. 243
  2. 81
  3. 99
  4. 100
Solución

Respuesta: 243

El while comprueba la condición antes de cada vuelta. Con n = 81, 81 < 100 es cierto y entra: n = 243. Después 243 < 100 es falso y sale. El valor final puede pasarse del límite.

Pregunta 10Rellenar huecos

Completa el bucle para sumar los números del 1 al 10 (ambos incluidos):

total = 0 y después for i in range(1, ____): con total ____ i dentro.

Palabras:

  • =
  • +=
  • 11
  • 10
  • -=
Solución

total = 0 y después for i in range(1, 11): con total += i dentro.

Como el final de range no se incluye, para llegar a 10 hay que poner 11. Y total += i acumula; con total = i solo te quedarías con el último.

Pregunta 11Única

¿Qué imprime este código?

cuenta = 0
for c in "Gran Canaria":
    if c == "a":
        cuenta += 1
print(cuenta)
  1. 4
  2. 5
  3. 3
  4. 2
Solución

Respuesta: 4

Es el patrón contador: empieza en 0 y suma 1 cada vez que se cumple la condición. Como 'a' == 'A' es falso, las mayúsculas no contarían.

Pregunta 12Respuesta corta

¿Qué imprime este programa? Escribe la salida exacta.

mayor = 0
for n in [4, 17, 9, 23, 8]:
    if n > mayor:
        mayor = n
print(mayor)
Solución

Respuesta: 23

Es el patrón máximo: guardas el mejor visto hasta ahora y lo cambias cuando aparece uno mayor. 4 → 17 → (9 no) → 23 → (8 no): queda 23.

Pregunta 13Única

¿Qué hace el else de este bucle?

for n in [3, 7, 11]:
    if n % 2 == 0:
        print("hay un par")
        break
else:
    print("ninguno es par")
  1. Se ejecuta porque el bucle terminó sin pasar por el break
  2. Se ejecuta en cada vuelta en la que el if es falso
  3. Da un error: un for no puede tener else
  4. No se ejecuta nunca
Solución

Respuesta: Se ejecuta porque el bucle terminó sin pasar por el break

El else de un for (o de un while) se ejecuta cuando el bucle acaba de forma normal, sin break. Va muy bien para búsquedas: «si no lo he encontrado…».

Míralo paso a paso en Python Tutor

En pythontutor.com, con Python 3, puedes ver el fallo del fragmento 2 en directo. Pega esta versión corta:

# Para Python Tutor: el break que solo sale del bucle de dentro
bandejas = ["NNC", "CNC", "NNN"]
num = 0
for bandeja in bandejas:
    num += 1
    hueco = 0
    for pieza in bandeja:
        hueco += 1
        if pieza == "C":
            print(num, hueco)
            break
print("fin")

Salida:

1 3
2 1
fin

Qué observar paso a paso:

  1. En la primera bandeja, pieza va tomando «N», «N» y «C»: un for sobre un texto recorre sus letras.
  2. Cuando pieza vale «C», se imprime 1 3 y la flecha salta del break a la línea del for bandeja de fuera, no al print("fin").
  3. num pasa a 2 y hueco vuelve a 0: el bucle de fuera sigue como si nada.
  4. En la bandeja 2 el chocolate está en el primer hueco: segundo print (2 1) y segundo break.
  5. La bandeja 3 se recorre entera (no hay «C») y por fin se imprime fin. Ahora prueba la versión con bandera y mira cómo la flecha sale de los dos bucles.

Chuletario: Bucles en Python

Lo esencial en 30 segundos: for cuando sabes cuántas vueltas habrá (recorre una secuencia o un range); while cuando no lo sabes (repite mientras la condición sea True, y algo dentro tiene que hacerla falsa). range nunca incluye el fin. break sale del bucle (solo del más interno); continue salta al siguiente elemento. Los acumuladores se preparan antes del bucle.

Quiero…CódigoResultado
Recorrer una listafor t in [3.5, 1.2]: print(t)3.5 y 1.2
Repetir N vecesfor i in range(3): print(i)0, 1, 2
Del 1 al 10range(1, 11)1 … 10
Cuenta atrásrange(5, 0, -1)5, 4, 3, 2, 1
De 2 en 2range(0, 11, 2)0, 2, 4, 6, 8, 10
Repetir mientras se cumpla algowhile cola > 0: cola -= 2para cuando cola ≤ 0
Salir al encontrar algoif t > 5: breaktermina el bucle
Saltar un casoif t == 0: continuepasa al siguiente
«Do while»while True: … if ok: breakal menos una vuelta
Imprimir en la misma líneaprint(x, end=" ")sin salto de línea
PatrónAntes del bucleDentro del bucle
Sumatotal = 0total += x
Contadorn = 0if cond: n += 1
Productop = 1p *= x
Máximomayor = lista[0]if x > mayor: mayor = x
Textotexto = ""texto += str(x) + " "
Búsqueda en dos buclesencontrado = Falseencontrado = True, break y, fuera, if encontrado: break

Plantillas de los ejercicios:

  • FizzBuzz: for i in range(1, 101): + if i % 3 == 0 and i % 5 == 0: primero → 10 líneas de 10.
  • Interés compuesto: anterior = capital → capital = round(capital * (1 + interes / 100), 2) → 1276.28 € en 5 años.
  • Primos: bandera es_primo = True por candidato + for divisor in range(2, int(n ** 0.5) + 1) + break → 10 primos hasta 30, 45 divisiones.
  • Ahorro: if ahorro <= 0 antes + while balance < objetivo: + mes // 12 y mes % 12 → 32 meses.
SíntomaCausa probable
El programa no terminawhile sin actualizar la variable, o continue antes de la actualización
Falta el último númerorange(1, n) en lugar de range(1, n + 1)
El bucle no hace nada y no da errorRango vacío: range(5, 0) sin -1, o condición de while falsa desde el principio
El total es solo el último valorAcumulador inicializado dentro del bucle
Encuentra «el primero» varias vecesbreak dentro de dos bucles: solo sale del de dentro
Todo da 0 al multiplicarAcumulador de productos que empieza en 0
NameError con el acumuladorNo se inicializó antes del bucle
IndexError en un while con listaLa condición deja pasar una vuelta de más (<= en lugar de <, o or en vez de and)

Antes de entregar, pregúntate:

  1. ¿Sé cuántas vueltas da cada bucle? ¿He elegido for o while por eso?
  2. En cada while, ¿qué línea acerca la condición a False, y se ejecuta en todas las vueltas?
  3. ¿Los range llegan exactamente hasta donde quiero (el fin no entra)?
  4. ¿Mis acumuladores se inicializan antes del bucle y con el valor correcto (0, 1 o "")?

Si te ha quedado alguna duda, vuelve a la teoría de bucles o repasa la práctica. Y si ya lo tienes, el siguiente tema son las funciones en Python: lo que hoy repetimos con bucles, mañana lo guardaremos con nombre propio.

Sigue aprendiendoTodos los artículos de Python

¿Te ha servido este artículo? Así puedes apoyar SergioLearns →

Sigue aprendiendo

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *