Bucles y recursividad para TAI: 8 ejercicios resueltos
Índice · 12 apartados
- Antes de empezar: una hoja de traza
- Ejercicio 1. Límite excluido y acumulador
- Ejercicio 2. Un while que duplica
- Ejercicio 3. Dos bucles no siempre forman un cuadrado
- Ejercicio 4. Continue, break y orden de instrucciones
- Ejercicio 5. Una suma recursiva y sus llamadas
- Ejercicio 6. Imprimir antes y después de la llamada
- Ejercicio 7. Valor devuelto frente a número de llamadas
- Ejercicio 8. Comparar recursividad e iteración
- Cómo revisar tus errores y seguir preparando TAI
- Fuentes y comprobación de los ejemplos
- Preguntas frecuentes
- ¿Los bucles y la recursividad están en el programa de TAI?
- ¿Estos ejercicios son preguntas oficiales del examen?
- ¿El último número de range se incluye en Python?
- ¿Qué diferencia hay entre break y continue?
- ¿Una función recursiva necesita un caso base?
- ¿Se puede ver una muestra del material TAI antes de comprar?
Para resolver bucles y recursividad en la preparación de TAI, sigue el código en orden y separa tres preguntas: cuántas veces se ejecuta una instrucción, qué valor termina teniendo una variable y qué devuelve una función. Pueden tener respuestas distintas. Una tabla de traza evita confundirlas.
El programa del anexo V de BOE-A-2025-26262 incluye bucles y recursividad en el bloque III, tema 2. Los ejemplos que siguen son ocho ejercicios originales, escritos en Python 3 y comprobados por ejecución. No son preguntas oficiales ni una predicción del lenguaje que pueda utilizar un examen. Aquí usamos Python para que el comportamiento sea concreto y reproducible; si otro enunciado usa un lenguaje diferente, aplica sus reglas.
Antes de empezar: una hoja de traza
En cada ejercicio, intenta resolver el enunciado antes de leer la solución. Escribe una fila por vuelta o por llamada. No saltes directamente al resultado porque reconozcas la forma de un algoritmo: una condición cambiada o una instrucción colocada antes de un incremento puede alterar la respuesta.
Para un bucle, prepara estas columnas: valor antes de comprobar la condición, resultado de esa condición, instrucciones ejecutadas y valor al terminar la vuelta. En un for, anota los valores que entrega el iterable. En un while, comprueba también qué instrucción cambia la variable de control y si puede quedar sin ejecutarse.
Para la recursividad, lleva dos registros: las llamadas que todavía están pendientes y el valor que devuelve cada una cuando termina. Una llamada no desaparece al invocar a la siguiente; puede quedar trabajo por hacer a su regreso.
Ejercicio 1. Límite excluido y acumulador
Pregunta: ¿qué imprime este fragmento?
total = 0
for value in range(1, 6):
total += value
print(total, value)
Solución: 15 5. Los valores recorridos son 1, 2, 3, 4 y 5. El 6 es el límite final y no se visita. El acumulador queda así:
| Valor recorrido | Total después de sumar |
|---|---|
| 1 | 1 |
| 2 | 3 |
| 3 | 6 |
| 4 | 10 |
| 5 | 15 |
La variable value sigue valiendo 5 después del bucle en este fragmento de Python. No pasa automáticamente a 6 al terminar. Tampoco debes generalizarlo a un rango vacío: si el bucle no ejecuta ninguna vuelta y la variable no estaba definida, no habrá recibido un valor por esta vía.
Qué se practica: distinguir límite, último elemento recorrido y suma. Si la pregunta pidiera el número de vueltas, la respuesta sería cinco, no quince.
Ejercicio 2. Un while que duplica
Pregunta: calcula el número de vueltas y el valor final de value.
value = 1
turns = 0
while value < 20:
value *= 2
turns += 1
print(turns, value)
Solución: 5 32. Las condiciones verdaderas se comprueban con 1, 2, 4, 8 y 16. En la quinta vuelta, el cuerpo transforma 16 en 32. La siguiente comprobación, 32 < 20, es falsa.
| Valor al comprobar | ¿Entra? | Valor tras duplicar |
|---|---|---|
| 1 | Sí | 2 |
| 2 | Sí | 4 |
| 4 | Sí | 8 |
| 8 | Sí | 16 |
| 16 | Sí | 32 |
| 32 | No | No ejecuta el cuerpo |
El resultado final puede superar el límite de la condición. Esta se evalúa antes del cuerpo, no después de cada operación. También hay seis comprobaciones de la condición, aunque solo cinco ejecuciones del cuerpo: la comprobación falsa que permite salir cuenta si eso es lo que pregunta el enunciado.
Ejercicio 3. Dos bucles no siempre forman un cuadrado
Pregunta: ¿cuántas veces se incrementa count?
count = 0
for row in range(1, 5):
for column in range(row):
count += 1
print(count)
Solución: 10. El bucle externo recorre cuatro valores. El interno ejecuta una, dos, tres y cuatro vueltas, respectivamente. Por tanto, el incremento ocurre 1 + 2 + 3 + 4 = 10 veces.
La cuenta de 16 supondría que el bucle interno realiza cuatro vueltas en todas las filas. Aquí su límite depende de row, por lo que cambia. Dibuja cuatro filas con uno, dos, tres y cuatro puntos si necesitas comprobar visualmente el recorrido.
Qué se practica: contar una instrucción concreta, no multiplicar por costumbre los límites que aparecen. Si el código imprimiera una línea después del bucle interno, esa otra instrucción se ejecutaría cuatro veces. La posición y la indentación determinan qué estás contando.
Ejercicio 4. Continue, break y orden de instrucciones
Pregunta: ¿qué valores llegan a sumarse?
total = 0
for value in range(1, 10):
if value % 2 == 0:
continue
if value == 7:
break
total += value
print(total, value)
Solución: 9 7. Se suman 1, 3 y 5. Los pares 2, 4 y 6 ejecutan continue, así que no llegan a la suma. El 7 no es par, pero alcanza el break y termina el bucle antes de sumarse. No se recorren 8 ni 9.
Este es un ejercicio sobre orden. Si la suma estuviera antes del break, el resultado sería diferente. Al seguir la traza, marca la instrucción que provoca el salto y tacha las que ya no se ejecutan en esa vuelta. No interpretes continue como «terminar todo el bucle»: significa continuar con su siguiente iteración.
Ejercicio 5. Una suma recursiva y sus llamadas
Entrada admitida: un entero no negativo. Para esta pregunta se usa 4.
def sum_to(number):
if number == 0:
return 0
return number + sum_to(number - 1)
print(sum_to(4))
Solución: 10. Se invocan sum_to(4), sum_to(3), sum_to(2), sum_to(1) y sum_to(0): cinco llamadas, incluida la inicial y el caso base.
Al llegar a cero, empieza la vuelta. sum_to(0) devuelve 0; sum_to(1) calcula 1 + 0; sum_to(2) calcula 2 + 1; sum_to(3) calcula 3 + 3; y la llamada inicial termina con 4 + 6.
| Llamada | Valor devuelto |
|---|---|
sum_to(0) | 0 |
sum_to(1) | 1 |
sum_to(2) | 3 |
sum_to(3) | 6 |
sum_to(4) | 10 |
No confundas cinco llamadas con cuatro descensos recursivos desde la llamada inicial. Define qué estás contando. Con una entrada negativa, esta implementación no se acercaría al caso base; por eso el dominio forma parte del enunciado, no es un detalle que puedas omitir.
Ejercicio 6. Imprimir antes y después de la llamada
Entrada admitida: entero no negativo. Traza visit(3).
def visit(number):
if number == 0:
return
print("B", number)
visit(number - 1)
print("A", number)
visit(3)
Solución, una línea por impresión:
B 3
B 2
B 1
A 1
A 2
A 3
Las impresiones B ocurren al bajar por las llamadas. Las A están pendientes hasta que termina la llamada siguiente. El caso cero regresa sin imprimir nada. Después se reanuda primero visit(1), luego visit(2) y por último visit(3).
Cada llamada conserva su propio parámetro. Al volver de visit(0), el parámetro de la llamada pendiente no se ha convertido en cero: sigue siendo 1. Dibujar una pila con una casilla por llamada ayuda a no atribuir a todas ellas una única variable compartida.
Ejercicio 7. Valor devuelto frente a número de llamadas
Entrada admitida: entero no negativo. Se cuentan todas las invocaciones, incluidas las que reciben cero.
calls = 0
def branches(number):
global calls
calls += 1
if number == 0:
return 0
return branches(number - 1) + branches(number - 1) + 1
result = branches(3)
print(result, calls)
Solución: 7 15. Hay una llamada con parámetro 3, dos con 2, cuatro con 1 y ocho con 0. La cuenta total es 1 + 2 + 4 + 8 = 15.
El valor devuelto se calcula de otra manera: para cero vale 0; para uno, 0 + 0 + 1 = 1; para dos, 1 + 1 + 1 = 3; y para tres, 3 + 3 + 1 = 7.
Las dos expresiones branches(number - 1) se ejecutan por separado. El código no guarda ni reutiliza el resultado de la primera. Aunque reciban el mismo argumento, cada una genera su propio conjunto de llamadas. El contador global se usa aquí solo para observar ese comportamiento y se inicia en cero antes de la ejecución que estamos midiendo.
Ejercicio 8. Comparar recursividad e iteración
Entrada admitida: entero no negativo. ¿Coinciden ambas funciones para 4 y para 0?
def factorial_recursive(number):
if number < 0:
raise ValueError("negative input")
if number <= 1:
return 1
return number * factorial_recursive(number - 1)
def factorial_iterative(number):
if number < 0:
raise ValueError("negative input")
result = 1
for factor in range(2, number + 1):
result *= factor
return result
print(factorial_recursive(4), factorial_iterative(4))
print(factorial_recursive(0), factorial_iterative(0))
Solución: la primera línea es 24 24 y la segunda, 1 1. En la versión iterativa con cero, el rango queda vacío y el acumulador mantiene su valor inicial, 1. En la recursiva, cero entra directamente en el caso base.
Para 4, la recursiva necesita las llamadas con 4, 3, 2 y 1. La iterativa multiplica por 2, 3 y 4. Producir el mismo resultado no implica ejecutar los mismos pasos ni usar los mismos recursos. No uses este ejemplo para concluir que la recursividad siempre es preferible o siempre debe evitarse: aquí interesa comparar su funcionamiento con entradas pequeñas. El tipo entero se presupone; la comprobación del código rechaza negativos, pero no valida todos los tipos posibles.
Cómo revisar tus errores y seguir preparando TAI
Después de estos ejercicios, clasifica cada fallo: límite excluido, instrucción omitida por un salto, estado final confundido con número de vueltas o retorno resuelto antes de tiempo. Repite primero el que corresponda a tu error y cambia una sola condición para observar su efecto. Si cambias varios elementos a la vez, será más difícil identificar qué regla no habías entendido.
Para practicar las decisiones de entrada en un bucle, tienes los ejercicios de condiciones booleanas para TAI. Si quieres seguir una aplicación concreta de un recorrido, continúa con búsqueda binaria y ejercicios resueltos. Son apoyos distintos: esta página se centra en trazar repeticiones y llamadas, no en sustituir todo el bloque de programación.
Puedes solicitar la muestra gratuita de Pack Temario TAI 2027 con nombre y correo para valorar una parte del material antes de comprar. Los ocho ejercicios de esta página son de acceso libre; la muestra es limitada y no equivale al curso completo. La ficha del temario TAI describe el desarrollo del programa, sus test y el material incluido. Consulta también el desglose del programa TAI para situar este apoyo dentro de tu preparación.
Fuentes y comprobación de los ejemplos
La vinculación al programa procede del anexo V, bloque III, tema 2 del BOE. Para las reglas del lenguaje se han consultado el tutorial oficial de control de flujo de Python y la referencia oficial de sentencias compuestas. Los enunciados, las tablas y las soluciones son originales. Los ocho fragmentos se han ejecutado de forma independiente para contrastar las salidas que se muestran.
Preguntas frecuentes
¿Los bucles y la recursividad están en el programa de TAI?
Sí. El anexo V de BOE-A-2025-26262, bloque III de Desarrollo de sistemas, tema 2, incluye bucles y recursividad dentro de los lenguajes de programación. Estos ejercicios son material original de estudio y no preguntas oficiales.
¿Estos ejercicios son preguntas oficiales del examen?
No. Son ocho ejercicios originales para practicar la lectura y la ejecución de código. No se atribuyen a ningún examen ni anticipan el lenguaje o el reparto de preguntas de una convocatoria futura.
¿El último número de range se incluye en Python?
No. Con paso positivo, range(1, 6) produce los enteros 1, 2, 3, 4 y 5. El límite final queda fuera. Hay que leer también el inicio y el paso, porque no todos los rangos empiezan en cero ni avanzan de uno en uno.
¿Qué diferencia hay entre break y continue?
break termina el bucle más interno que lo contiene. continue omite lo que queda de la vuelta actual y pasa a la siguiente iteración; en un while se vuelve a comprobar la condición. Ninguno equivale a return, que sale de la función.
¿Una función recursiva necesita un caso base?
Necesita una condición de terminación adecuada y llamadas que se acerquen a ella para las entradas admitidas. Tener un caso base no basta si las llamadas nunca llegan a alcanzarlo. En los ejemplos se indica el dominio de entrada.
¿Se puede ver una muestra del material TAI antes de comprar?
Sí. La página de muestra TAI permite solicitar una parte del material con nombre y correo. Es una muestra limitada; no equivale al curso completo. Los ocho ejercicios de este artículo se pueden leer sin registro.
Más sobre esta oposición