Práctica 2.4: Depurar programas
P2.4 - Depuración del algoritmo burbuja¶
En esta práctica vas a investigar un error de lógica en un programa que ordena
una lista mediante el algoritmo burbuja. Primero reproducirás el comportamiento
incorrecto, después formularás una hipótesis y utilizarás el depurador para
observar i, j y la lista en cada comparación. Por último, corregirás el
programa y demostrarás que funciona con datos normales, repetidos y límite.
El resultado esperado no es solo una lista ordenada: también debes poder explicar qué observaste, qué hipótesis comprobaste y por qué la corrección resuelve el problema.
1. Objetivos¶
- Explicar el funcionamiento de dos bucles anidados que comparan elementos adyacentes.
- Reproducir un error de lógica con una entrada conocida y diferenciar el resultado obtenido del resultado esperado.
- Formular una hipótesis comprobable antes de modificar el código.
- Colocar puntos de interrupción, ejecutar paso a paso e inspeccionar variables en Visual Studio Code.
- Corregir el algoritmo y verificarlo con listas desordenadas, ordenadas, repetidas, vacías y de un solo elemento.
- Documentar las pruebas y las evidencias de depuración para que otra persona pueda repetirlas.
2. Relación con RA y criterios de evaluación¶
| Código | Descripción literal de la normativa |
|---|---|
| RA 3 | Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje. |
| CE 3.f | Se han probado y depurado los programas. |
Las evidencias se concretan así:
- CE 3.f: los ejercicios 2.4.1 y 2.4.2 incluyen la reproducción del fallo, la hipótesis, la observación paso a paso, la corrección y las pruebas de casos normales y frontera.
- El
README.mddel ejercicio 2.4.3 conserva los resultados esperados y obtenidos, la explicación de la corrección y las dos evidencias de depuración.
3. Requisitos y recursos¶
- Python 3.9 o posterior, un editor y una terminal para ejecutar los programas.
- Visual Studio Code con la extensión Python de Microsoft. Si utilizas otro IDE, emplea sus controles equivalentes y conserva las mismas evidencias.
- Conocimientos de listas,
for,range, condiciones, funciones y copia de listas. - Lectura previa de la teoría de sentencias iterativas y de salto.
- Lectura de la teoría de depuración de programas, especialmente los apartados sobre hipótesis, breakpoints, Variables y ejecución paso a paso.
- La presentación de depuración como repaso visual.
La práctica utiliza una lista pequeña para que puedas calcular a mano el
resultado de cada comparación. No uses list.sort() ni sorted() para ordenar
la lista del algoritmo: sorted() se reservará para una aserción de desarrollo
que compruebe el resultado final.
4. Pasos a seguir¶
4.1. Preparar el trabajo y reproducir el problema¶
-
Crea una carpeta de trabajo llamada
practica_u2_4_depurar_burbujacon los archivosejercicio2.4.1.py,ejercicio2.4.2.pyyREADME.md. -
Copia el siguiente programa inicial en
ejercicio2.4.1.py. El error está intencionado y es de lógica, no de sintaxis.def ordenar_burbuja(valores: list[int]) -> list[int]: """Devuelve una copia de la lista ordenada mediante burbuja.""" lista = valores.copy() for i in range(len(lista) - 1): for j in range(len(lista) - 1 - i): if lista[j] < lista[j + 1]: lista[j], lista[j + 1] = lista[j + 1], lista[j] return lista datos = [8, 3, 1, 19, 14] resultado = ordenar_burbuja(datos) print("Entrada:", datos) print("Resultado:", resultado) -
Ejecuta el archivo desde la terminal:
-
Anota en el
README.mdel resultado obtenido y el resultado esperado. Para[8, 3, 1, 19, 14], la salida esperada en orden ascendente es[1, 3, 8, 14, 19]. No cambies todavía el código.
4.2. Formular una hipótesis¶
-
Describe en el
README.mdla diferencia entre el resultado obtenido y el esperado. Indica si el problema es de sintaxis, de ejecución o de lógica, y justifica la respuesta. -
Escribe una hipótesis concreta antes de abrir el depurador. Por ejemplo: «La condición del
ifintercambia los valores en el orden contrario al que necesita una ordenación ascendente». Puedes formular otra hipótesis, pero debe poder comprobarse observandolista[j]ylista[j + 1]. -
Coloca un punto de interrupción en la línea del
ifhaciendo clic en el margen izquierdo o pulsando F9. Inicia la depuración con Run and Debug y F5.
4.3. Observar el estado paso a paso¶
-
Cuando la ejecución se detenga, comprueba en Variables los valores de
i,jylista. Recuerda que la línea resaltada es la próxima instrucción que se ejecutará, no una instrucción ya ejecutada. -
Pulsa F10 para avanzar sin entrar en una función y observa qué ocurre después de cada comparación. Añade
lista,iyjal panel Watch si necesitas mantenerlos visibles. -
En la primera comparación,
lista[j]vale8ylista[j + 1]vale3. Comprueba si la condición permite el intercambio que necesita el orden ascendente. Sigue al menos una comparación en la que sí se intercambien los valores y anota el estado anterior y posterior de la lista. -
Cambia únicamente la condición que has investigado para que se intercambien los elementos cuando el de la izquierda sea mayor que el de la derecha. Ejecuta de nuevo el programa y comprueba que la salida coincide con la esperada.
-
Guarda en el
README.mduna evidencia de la sesión: una captura en la que se vea el punto de interrupción y otra en la que se distingan los valores dei,jylista. Si una sola captura contiene ambas evidencias, explica qué representa cada elemento.
4.4. Mejorar y verificar la implementación¶
-
Copia el algoritmo corregido en
ejercicio2.4.2.pyy añade una variablehubo_intercambiopara detener los recorridos cuando una pasada completa no haya cambiado la lista. Inicializa esa variable al principio de cada pasada. -
Coloca la asignación
hubo_intercambio = Truedentro del intercambio y usa esa variable en la condición de continuación del bucle exterior. Comprueba con el depurador que una lista ya ordenada necesita menos pasadas. -
Añade una aserción de desarrollo después de llamar a la función. La aserción compara el resultado del algoritmo con una referencia, pero no sustituye al algoritmo que estás practicando.
-
Prueba, como mínimo, estos casos y anota la salida esperada antes de ejecutarlos:
[8, 3, 1, 19, 14],[1, 2, 3, 4],[4, 3, 2, 1],[3, 1, 3, 2],[]y[7]. -
Comprueba que la función devuelve una copia ordenada y que la lista original no cambia. Si la aserción falla, vuelve al depurador y observa el primer estado en el que el resultado deja de coincidir con tu hipótesis.
4.5. Documentar las comprobaciones finales¶
-
Completa el
README.mdcon tu nombre o identificador, el entorno utilizado, la hipótesis inicial, los casos de prueba, los resultados obtenidos y las decisiones tomadas durante la depuración. -
Incluye dos evidencias de depuración: un punto de interrupción activo y una inspección de variables durante una comparación. No incluyas datos personales ni información sensible en las capturas.
-
Retira cualquier
print()obreakpoint()temporal que hayas añadido para investigar. El programa final debe conservar solo las salidas necesarias y la aserción de desarrollo solicitada. -
Ejecuta de nuevo los dos archivos desde la terminal y copia en el
README.mduna salida final que demuestre que el caso principal termina correctamente.
5. Comprobaciones de finalización¶
ejercicio2.4.1.pyordena[8, 3, 1, 19, 14]como[1, 3, 8, 14, 19].ejercicio2.4.2.pyutiliza dos bucles, reduce el rango de comparaciones en cada pasada y puede terminar antes cuando no hay intercambios.- Los dos programas se ejecutan sin errores de sintaxis ni excepciones de índice.
- Se han comprobado una lista desordenada, una ordenada, una invertida, una con duplicados, una vacía y otra con un solo elemento.
- La lista original no se modifica porque la función trabaja sobre una copia.
- La aserción de desarrollo pasa y se entiende que sirve para comprobar el código durante el desarrollo, no para validar una entrada externa.
- El
README.mdcontiene la hipótesis, los resultados esperados y obtenidos, las decisiones de depuración y las dos evidencias solicitadas. - El código no conserva
breakpoint()ni mensajes temporales de investigación.
6. Ejercicios y entregables¶
- Ejercicio 2.4.1 — Corregir el orden. Depura el programa inicial, demuestra que produce un orden incorrecto, localiza la comparación que causa el problema y corrígela sin modificar el resto del algoritmo hasta haber comprobado la hipótesis.
- Ejercicio 2.4.2 — Evitar pasadas innecesarias. Implementa la variante
que usa
hubo_intercambio, depúrala con una lista ya ordenada y añade la aserción de desarrollo indicada. - Ejercicio 2.4.3 — Informe de depuración. Completa el
README.mdcon una tabla o lista de casos de prueba, la hipótesis, la explicación de la corrección y las evidencias de la sesión. Relaciona al menos una observación dei,jylistacon el resultado final. - Entregables. Entrega
ejercicio2.4.1.py,ejercicio2.4.2.pyyREADME.md. El README debe incluir tu nombre o identificador, el entorno, los casos probados, los resultados esperados y obtenidos, la hipótesis, la explicación de la solución, la aserción utilizada y las dos evidencias de depuración.
7. Solución orientativa¶
En el primer ejercicio, una ordenación ascendente solo debe intercambiar dos valores adyacentes cuando el valor de la izquierda sea mayor que el de la derecha. La condición inicial usaba el signo contrario, por eso desplazaba los valores mayores hacia el principio y producía un orden descendente.
Una posible solución para el segundo ejercicio es la siguiente:
def ordenar_burbuja(valores: list[int]) -> list[int]:
"""Devuelve una copia de valores ordenada de menor a mayor."""
lista = valores.copy()
i = 0
hubo_intercambio = True
while i < len(lista) - 1 and hubo_intercambio:
hubo_intercambio = False
for j in range(len(lista) - 1 - i):
if lista[j] > lista[j + 1]:
lista[j], lista[j + 1] = lista[j + 1], lista[j]
hubo_intercambio = True
i += 1
return lista
datos = [8, 3, 1, 19, 14]
resultado = ordenar_burbuja(datos)
assert resultado == sorted(datos)
print("Entrada:", datos)
print("Resultado:", resultado)
El resultado esperado de este ejemplo es:
No se exige copiar esta implementación literalmente. Para contrastar la
solución, comprueba que la comparación, el límite len(lista) - 1 - i, el
intercambio, la condición de parada temprana y la copia de la lista cumplen su
propósito. Una AssertionError debe llevarte a revisar el estado observado,
no a eliminar la aserción sin investigar la causa.
8. Fuentes y referencias¶
- Teoría de sentencias iterativas y de salto de la unidad.
- Teoría de depuración de programas de la unidad.
- Documentación oficial de Python: estructuras de control.
- Documentación oficial de Python:
assert. - Visual Studio Code: depuración de Python.
- Normativa oficial del título de Desarrollo de Aplicaciones Web.