Este tutorial adapta pedagógicamente el Día 5 del curso. Las secciones 📝 Ejercicio original del curso provienen de los archivos del curso. Los retos 🟢🟡🟠🔴, el proyecto extra y el proyecto integrador son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.
Tabla de contenidos
- Antes de empezar: la seguridad de tus contraseñas
- El bucle
forcon listas - Acumuladores: reconstruir
sum()ymax() forconrange()- 🚀 Proyecto del día: Generador de Contraseñas
- 🌟 Proyecto extra: Analizador del Simulacro Saber 11
- 🏆 Proyecto integrador del Día 5: ¿Es justo el azar?
- 🤖 Programar con apoyo de IA
- 🛠️ Correcciones técnicas al material original
- 📋 Matriz de trazabilidad
- 📦 Evidencias de aprendizaje del Día 5
0. Antes de empezar: la seguridad de tus contraseñas
(Fuente: 037 - Day 5 Goals- what we will make by the end of the day.md, 042 - Hard Work and Perseverance beats Raw Talent Every Time.md)
Una de las formas más comunes de "hackear" cuentas es la reutilización de contraseñas. Cuando un sitio web sufre una filtración, los atacantes prueban el mismo correo y la misma contraseña en muchos otros servicios. El curso recomienda revisar en haveibeenpwned.com (se abre en otra pestaña) si tu correo aparece en alguna filtración conocida, y usar contraseñas únicas y robustas para cada sitio.
Hoy construiremos un generador de contraseñas. Para eso necesitamos bucles: instrucciones que se repiten.
El mensaje de cierre del curso para hoy: el trabajo duro y la perseverancia le ganan al talento. Si hoy sientes que "esto no es para ti", es normal. Sigue practicando: en algún momento todo empieza a encajar.
Prerequisito general: listas y
random(Día 4),if(Día 3) y+=(Día 2).
1. El bucle for con listas
(Fuente: 038 - Using the for loop with Python Lists.md)
Prerequisito: listas (Día 4, Tema 2) y sangría en bloques (Día 3).
🎯 Objetivo de aprendizaje
- Recorrer una lista con
fory hacer algo con cada elemento. - Distinguir el código que está dentro del bucle (con sangría) del que está fuera.
🧠 ¿Qué aprenderemos?
- ¿Qué es un bucle?
- Sintaxis
for elemento in lista:. - La variable temporal del bucle.
- Seguimiento paso a paso con Thonny.
📖 Explicación conceptual
Un bucle repite un bloque de código. Bart Simpson, castigado a escribir la misma frase cien veces en el tablero, se habría ahorrado el trabajo si supiera programar.
frutas = ["Manzana", "Durazno", "Pera"]
for fruta in frutas:
print(fruta)Cómo se lee: "por cada fruta en frutas, haz lo que está en el bloque con sangría".
foreinson palabras clave.frutaes una variable temporal. En cada vuelta toma el valor del siguiente elemento: primero"Manzana", después"Durazno"y por último"Pera".- Los dos puntos y la sangría funcionan igual que en el
if.
Dentro frente a fuera del bucle
for fruta in frutas:
print(fruta)
print(fruta + " en torta") # dentro: se repite 3 veces
print(frutas) # fuera: se ejecuta 1 vez, al terminar el bucle💡 Recomendación del curso: si no ves claro cómo avanza el bucle, ejecútalo en Thonny con el depurador. En el panel de variables verás cómo
frutacambia de valor en cada vuelta.
🔎 Ejemplo explicado: lista de asistencia
curso = ["Sara", "Tomás", "Luisa", "Mateo"]
for estudiante in curso:
print(f"Llamando a lista: {estudiante}... ¡Presente!")
print(f"Total de estudiantes: {len(curso)}")- Qué problema resuelve: aplica la misma acción a cada estudiante sin escribir un
printpor persona. - Resultado esperado: cuatro líneas "Llamando a lista…" y, al final, una sola línea con el total.
- Observa: si mañana llegan 10 estudiantes nuevos a la lista, el código no cambia.
⚠️ Errores frecuentes
1. Olvidar los dos puntos o la sangría → SyntaxError o IndentationError, igual que con if.
2. Poner con sangría algo que debía ejecutarse una sola vez
- Qué ocurre: el total se imprime 4 veces.
- Cómo solucionarlo: saca esa línea del bloque del bucle.
3. Usar la lista en lugar de la variable temporal
- Qué ocurre:
print(curso)dentro del bucle imprime la lista completa en cada vuelta. - Cómo solucionarlo: dentro del bucle usa la variable temporal (
estudiante).
📝 Ejercicio original del curso: ejercicio de codificación posterior
La lección remite a "un ejercicio de codificación" en la lección siguiente. El archivo siguiente suministrado (039) trabaja la puntuación más alta (Tema 2). Si existe un ejercicio intermedio, su enunciado no está incluido entre los archivos suministrados.
Retos adicionales (creados para esta adaptación)
🟢 Reto 1: Aplicación
Recorre una lista de 5 ciudades de Colombia e imprime "Me gustaría visitar ..." para cada una.
🟡 Reto 2: Ampliación
Recorre una lista de palabras e imprime cada palabra junto con su número de letras.
🟠 Reto 3: Desafío
Recorre una lista de precios e imprime solo los que superen $10 000. Al final, fuera del bucle, muestra cuántos fueron.
🔴 Reto 4: Pensamiento computacional
Tienes dos listas del mismo tamaño: nombres y notas. Sin conocer todavía técnicas avanzadas, ¿cómo recorrerías ambas "en paralelo" para imprimir "Sara: 4.5"? Diseña una solución con lo que sabes. (Pista: un índice que aumenta.) Luego investiga la función zip() y compara las dos soluciones.
🧩 Comprueba lo aprendido: Tema 1
- Predicción: ¿cuántas líneas imprime este código?
for x in ["a", "b", "c"]:
print(x)
print("-")
print("fin")- Depuración: este código debería imprimir cada color, pero imprime la lista completa 3 veces. Corrígelo:
colores = ["rojo", "verde", "azul"]
for color in colores:
print(colores)- Creación: con una lista de tareas pendientes, imprímelas numeradas (1., 2., 3., …) usando una variable contador.
Evidencia: Reto 4 resuelto con las dos estrategias.
2. Acumuladores: reconstruir sum() y max()
(Fuente: 039 - Highest Score.md)
Prerequisito: Tema 1,
+=(Día 2) eif(Día 3).
🎯 Objetivo de aprendizaje
- Usar un acumulador dentro de un bucle para calcular totales.
- Encontrar el valor máximo de una lista usando bucles y condicionales.
- Entender que las funciones incorporadas (
sum,max) están construidas con estas mismas piezas básicas.
📖 Explicación conceptual
Python trae funciones listas para usar con números:
puntajes = [150, 142, 185, 120, 171, 184, 149, 24, 59, 68, 199, 78, 65, 89, 86, 55, 91, 64, 89]
print(sum(puntajes)) # suma todos los elementos
print(max(puntajes)) # el mayor(En el curso, la lista de puntajes da una suma de 2068 y un máximo de 199. La lista completa del ejercicio no está incluida entre los archivos suministrados, así que la de arriba es un ejemplo con valores parecidos.)
¿Cómo haríamos sum() nosotros mismos? Con el patrón acumulador:
total = 0 # 1. valor inicial, ANTES del bucle
for puntaje in puntajes:
total += puntaje # 2. se actualiza en cada vuelta
print(total) # 3. se usa DESPUÉS del bucleUn acumulador es una variable que "va juntando" resultados en cada vuelta del bucle. Es el mismo patrón de la cuenta de la pizza del Día 3, pero ahora automatizado.
🔎 Ejemplo explicado: seguimiento del máximo, paso a paso
puntaje_maximo = 0
for puntaje in puntajes:
if puntaje > puntaje_maximo:
puntaje_maximo = puntaje
print(puntaje_maximo)| Vuelta | puntaje |
¿puntaje > puntaje_maximo? |
puntaje_maximo después |
|---|---|---|---|
| 1 | 150 | 150 > 0 ✅ | 150 |
| 2 | 142 | 142 > 150 ❌ | 150 |
| 3 | 185 | 185 > 150 ✅ | 185 |
| … | … | … | … |
No hace falta un else: si el puntaje no es mayor, simplemente no se hace nada.
⚠️ Errores frecuentes
1. Inicializar el acumulador dentro del bucle
- Qué ocurre:
total = 0dentro delforreinicia la suma en cada vuelta, y al final solo queda el último valor. - Cómo solucionarlo: inicializa antes del bucle.
2. Usar sum o max como nombre de variable
- Qué ocurre: después de
sum = 0, la funciónsum()deja de existir en ese programa ysum(puntajes)produceTypeError: 'int' object is not callable. - Cómo solucionarlo: usa nombres como
totalopuntaje_maximo(Día 1: no uses nombres de funciones incorporadas).
🛠️ Nota técnica: en el video, la variable del acumulador se llama
sum, justo después de haber usado la funciónsum(). Funciona en esa demostración porque ya no se vuelve a llamar asum(), pero es una mala práctica que el propio curso desaconseja en el Día 1.
3. Empezar el máximo en 0 con valores negativos
- Qué ocurre: con
[-5, -2, -9]el resultado es 0, un valor que ni siquiera está en la lista. - Cómo solucionarlo: inicializa con el primer elemento:
puntaje_maximo = puntajes[0].
📝 Ejercicio original del curso: puntaje más alto
Enunciado: sin usar max(), encuentra el puntaje más alto de la lista usando un bucle for y un if.
Resultado esperado (con la lista del curso): 199.
🔍 Antes de programar
- ¿Qué necesitas "recordar" mientras recorres la lista?
- ¿Con qué valor debe empezar esa variable?
- ¿Qué comparación haces en cada vuelta?
Retos adicionales (creados para esta adaptación)
🟢 Reto 1: Aplicación
Calcula el mínimo sin usar min().
🟡 Reto 2: Ampliación
Calcula el promedio sin usar sum() ni len(): usa dos acumuladores, uno para el total y otro para contar elementos.
🟠 Reto 3: Desafío
Cuenta cuántos puntajes están por encima del promedio. (Requiere dos recorridos: uno para calcular el promedio y otro para contar.)
🔴 Reto 4: Pensamiento computacional
Encuentra el segundo puntaje más alto en un solo recorrido de la lista. Diseña primero una tabla de seguimiento como la del ejemplo, con dos variables. ¿Qué pasa si el máximo aparece repetido?
🧩 Comprueba lo aprendido: Tema 2
- Predicción: ¿qué imprime este código?
total = 0
for n in [3, 5, 2]:
total += n * 2
print(total)- Depuración: el siguiente código siempre imprime el último número de la lista. ¿Por qué?
for n in numeros:
total = 0
total += n
print(total)- Creación: cuenta cuántas palabras de una lista empiezan por la letra "a".
Evidencia: tabla de seguimiento del Reto 4.
3. for con range()
(Fuente: 040 - for loops and the range() function.md)
Prerequisito: Tema 2.
🎯 Objetivo de aprendizaje
- Generar secuencias de números con
range(inicio, fin, paso). - Repetir una acción un número determinado de veces, sin necesidad de una lista.
📖 Explicación conceptual
La historia de Gauss. A los 10 años, a Carl Friedrich Gauss le pusieron a sumar los números del 1 al 100 para tenerlo ocupado. Lo resolvió en minutos al notar que 1 + 100, 2 + 99, 3 + 98… siempre dan 101, y que hay 50 de esas parejas: 50 × 101 = 5050.
Nosotros podemos "ganarle" a Gauss con un bucle y range():
| Forma | Genera | Ejemplo | Resultado |
|---|---|---|---|
range(fin) |
de 0 hasta fin − 1 |
range(4) |
0, 1, 2, 3 |
range(inicio, fin) |
de inicio hasta fin − 1 |
range(1, 11) |
1, 2, …, 10 |
range(inicio, fin, paso) |
saltando de paso en paso |
range(1, 11, 3) |
1, 4, 7, 10 |
⚠️ El límite superior NO se incluye. Para llegar hasta 10, escribe
range(1, 11).
range() por sí sola no imprime nada: print(range(1, 10)) muestra range(1, 10). Se usa junto con for:
for numero in range(1, 11):
print(numero)La forma de un solo argumento, range(fin), no aparece en esta lección, pero el curso la usa en el proyecto del día.
🔎 Ejemplo explicado: el reto de Gauss
total = 0
for numero in range(1, 101):
total += numero
print(total) # 5050- Por qué
101: para que el 100 quede incluido. - Patrón: es el mismo acumulador del Tema 2, pero ahora recorre números generados en lugar de una lista.
⚠️ Errores frecuentes
- Desfase por uno:
range(1, 100)se detiene en 99. Imprime el primer y el último valor para verificar. - Olvidar la conversión:
range(1, input("Hasta: "))produceTypeError, porquerangenecesita enteros. Usaint(input(...)). - Paso que nunca llega:
range(10, 1)no genera nada, porque va "hacia arriba" por defecto. Para contar hacia atrás usa un paso negativo:range(10, 0, -2)→ 10, 8, 6, 4, 2.
📝 Ejercicio original del curso: el reto de Gauss
Enunciado: suma todos los números del 1 al 100 usando for y range().
Resultado esperado: 5050.
📝 Ejercicio original del curso: reto de range() posterior
La lección remite a "un reto usando la función range()" en la lección siguiente. Su enunciado no está incluido entre los archivos suministrados.
Retos adicionales (creados para esta adaptación)
🟢 Reto 1: Aplicación
Suma todos los números pares entre 1 y 100. Resuélvelo de dos formas: con un paso de 2 y con if y %. (Resultado esperado: 2550.)
🟡 Reto 2: Ampliación
Pide un número y muestra su tabla de multiplicar del 1 al 10.
🟠 Reto 3: Desafío: conteo regresivo
Pide un número de segundos y haz un conteo regresivo hasta 1 que termine en "¡Despegue! 🚀".
🔴 Reto 4: Pensamiento computacional: FizzBuzz
Para los números del 1 al 100: si el número es múltiplo de 3, imprime "Fizz"; si es múltiplo de 5, "Buzz"; si es múltiplo de ambos, "FizzBuzz"; en cualquier otro caso, el número. Este es un problema clásico de las entrevistas de programación. Piensa bien el orden de las condiciones (recuerda el Día 3).
🧩 Comprueba lo aprendido: Tema 3
- Predicción: ¿qué valores generan
range(5),range(2, 8, 2)yrange(5, 0, -1)? - Conceptual: ¿cuál es la diferencia entre
for x in listayfor i in range(len(lista))? - Creación: imprime un triángulo de asteriscos de altura
n. (Pista:"*" * 3da"***".)
Evidencia: Reto 4 (FizzBuzz) verificado para los números 1 a 15.
4. 🚀 Proyecto del día: Generador de Contraseñas
(Fuente: 041 - Day 5 Project- Create a Password Generator.md, proyecto oficial del curso original)
Problema
Generar contraseñas robustas a partir de la cantidad de letras, símbolos y números que pida el usuario.
Objetivo
El programa pregunta cuántas letras, cuántos símbolos y cuántos números quiere el usuario, y genera una contraseña con esos caracteres.
El curso propone dos niveles:
| Nivel | Resultado | Ejemplo (4 letras, 2 símbolos, 2 números) |
|---|---|---|
| Fácil | En orden: primero letras, luego símbolos, luego números | fKqa$#48 |
| Difícil | Caracteres en orden totalmente aleatorio | 4f$Kq8a# |
Restricciones técnicas
El código inicial del curso trae tres listas: letters (a–z y A–Z), numbers (0–9) y symbols (por ejemplo ! # $ % & ( ) * +). Ese archivo no está incluido entre los materiales suministrados, así que debes crear tú las listas. Usa for, range(), random y listas.
🔍 Antes de programar
- ¿Cuántas veces debe repetirse la selección de una letra? ¿De dónde sale ese número?
- ¿Dónde vas a "acumular" los caracteres: en un string o en una lista?
- ¿Por qué el nivel fácil es inseguro? (El curso lo explica: si el atacante sabe que los dos últimos caracteres son siempre números, solo tiene que probar 100 combinaciones para esa parte.)
Construcción paso a paso
Versión 1: nivel fácil, solo letras. Empieza con contrasena = "" y usa un bucle que se repita tantas veces como letras pidió el usuario. En cada vuelta, contrasena += random.choice(letras). Imprime la contraseña dentro del bucle para ver cómo crece, y después saca el print del bucle.
Discusión del curso sobre el rango: con
range(1, nr_letras)y 4 letras solo se generan 3 (desfase por uno). La solución esrange(1, nr_letras + 1)o, más simple,range(0, nr_letras), que equivale arange(nr_letras). Ambas son válidas; el curso prefiere la segunda por ser más limpia.
Versión 2: nivel fácil completo. Repite el patrón para símbolos y números.
Versión 3: nivel difícil.
- Cambia el acumulador por una lista:
lista_contrasena = []ylista_contrasena.append(...). - Mezcla la lista. El curso encuentra la solución buscando en Stack Overflow "cómo cambiar el orden de los elementos de una lista en Python": la función
random.shuffle(lista). Ojo:shufflemodifica la lista en su lugar y no devuelve nada. - Convierte la lista de vuelta a string con un bucle y un acumulador
+=.
Alternativa (ampliación de esta adaptación):
"".join(lista_contrasena)convierte la lista en string en una sola línea.
Pruebas
| Letras | Símbolos | Números | Verificar |
|---|---|---|---|
| 4 | 2 | 2 | La longitud total es 8 |
| 12 | 3 | 4 | La longitud es 19 y el orden cambia en cada ejecución (nivel difícil) |
| 0 | 0 | 5 | Solo contiene dígitos |
| 0 | 0 | 0 | Contraseña vacía. ¿Debería advertirlo el programa? |
🧪 Prueba y depuración
Este código tiene tres errores:
import random
lista = []
for i in range(1, nr_letras):
lista.append(random.choice(letras))
lista = random.shuffle(lista)
contrasena = ""
for caracter in lista:
contrasena += caracter(Pistas: un desfase por uno, un valor de retorno que se pierde y un problema de sangría.)
🛠️ Nota técnica de seguridad: el módulo
randomno es criptográficamente seguro (ver Día 4). Para contraseñas reales, la documentación oficial recomienda el módulosecrets(se abre en otra pestaña), que tienesecrets.choice(). Para mezclar,random.SystemRandom().shuffle()usa una fuente segura. Extensión: adapta tu generador asecretsy explica la diferencia.
⭐ Extensión del proyecto
- Garantizar al menos una letra mayúscula y una minúscula.
- Validar que la contraseña tenga al menos 8 caracteres en total. Si no, avisar al usuario.
- Generar 5 contraseñas de una vez para que el usuario elija la que prefiera.
5. 🌟 Proyecto extra: Analizador del Simulacro Saber 11
Situación
Después del simulacro de las pruebas Saber 11, la coordinación tiene los puntajes globales (de 0 a 500) de un curso y necesita un informe rápido.
Objetivo
A partir de una lista de puntajes, calcular con bucles, sin usar sum, max, min ni len:
- El número de estudiantes.
- El promedio.
- El puntaje más alto y el más bajo.
- Cuántos estudiantes obtuvieron 300 puntos o más.
- Una "barra" de asteriscos por estudiante: un
*por cada 50 puntos, calculada con//.
Casos de prueba
Con puntajes = [312, 287, 405, 251, 356]: 5 estudiantes, promedio 322.2, máximo 405, mínimo 251 y 3 estudiantes con 300 puntos o más.
Decisiones de diseño
- ¿Con qué valor inicializas el máximo y el mínimo? (Recuerda el error frecuente 3 del Tema 2.)
- ¿Cuántos recorridos de la lista necesitas? ¿Puedes hacerlo todo en uno solo?
⭐ Extensión
Pide los puntajes al usuario: primero cuántos estudiantes son y luego un bucle con range() que pida cada puntaje y lo agregue con append().
6. 🏆 Proyecto integrador del Día 5: ¿Es justo el azar?
Proyecto integrador creado para esta adaptación. Combina
random(Día 4), listas, bucles, acumuladores, condicionales y f-strings.
Situación problema
En el Día 4 construimos juegos que "confían" en el azar. Pero ¿realmente cada cara de un dado sale 1 de cada 6 veces? Vamos a hacer un experimento científico con código.
Pregunta orientadora
¿Cuántas repeticiones hacen falta para que los resultados de un dado se acerquen a lo que predice la probabilidad?
Requerimientos
- Pedir al usuario cuántos lanzamientos simular.
- Usar una lista de 6 contadores,
[0, 0, 0, 0, 0, 0], y en cada lanzamiento aumentar el contador de la cara obtenida. (Pista: la caraccorresponde al índicec - 1.) - Al final, mostrar para cada cara: la frecuencia, el porcentaje con un decimal y una barra de
*proporcional. - Mostrar la diferencia entre la cara más frecuente y la menos frecuente.
- Para poder probar, agregar la opción de fijar la "semilla" del generador con
random.seed(numero): con la misma semilla, los resultados se repiten exactamente. (Investiga en la documentación.)
Etapas
- Simulación con
foryrange, imprimiendo los primeros 10 lanzamientos para verificar. - Contadores en la lista.
- Informe con porcentajes y barras.
- Experimenta con 10, 100, 1000 y 100 000 lanzamientos y registra los resultados en una tabla.
Entregables
- Código funcional.
- Tabla del experimento.
- Conclusión escrita: ¿qué pasa con los porcentajes a medida que aumenta el número de lanzamientos? (Esta es la ley de los grandes números.)
Criterios técnicos
- La suma de las 6 frecuencias es igual al número de lanzamientos. Verifícalo en el código.
- Con la misma semilla se obtiene el mismo resultado.
- No hay desfase por uno en los índices.
Posibles extensiones
Simula la suma de dos dados (valores del 2 al 12) y observa cuál sale más. ¿Por qué ya no son todas igual de probables?
7. 🤖 Programar con apoyo de IA
En el proyecto de hoy, el curso resolvió la parte difícil buscando en Stack Overflow ("cómo cambiar el orden de una lista en Python"). Hoy muchas personas harían esa pregunta a una IA. En cualquiera de los dos casos, la habilidad importante es la misma: formular bien la pregunta y verificar la respuesta.
Actividad: la contraseña "segura". Pregúntale a una IA: "Escribe un generador de contraseñas en Python". Luego analiza:
- ¿Usa
randomosecrets? Contrasta con la documentación desecrets(se abre en otra pestaña). - ¿Tiene desfases por uno en
range? Pruébalo contando la longitud del resultado. - ¿Hay alguna instrucción que no entiendas? Explícala con tus palabras o reemplázala por algo que sí entiendas.
8. 🛠️ Correcciones técnicas al material original
| Archivo | Afirmación o práctica en el curso | Observación | Tratamiento |
|---|---|---|---|
039 |
Se usa sum como nombre de variable |
Oculta la función sum(); si se vuelve a llamar, produce TypeError |
Error frecuente 2 del Tema 2 |
039 |
max_score = 0 como valor inicial |
Falla con listas de números negativos | Error frecuente 3 del Tema 2 |
039 |
Lista de puntajes (suma 2068, máximo 199) | La lista completa no está en los archivos suministrados | Lista de ejemplo, advertida como tal |
041 |
Generador de contraseñas con random |
random no es seguro para contraseñas; la documentación oficial recomienda secrets |
Nota técnica del proyecto |
041 |
random.shuffle |
Modifica la lista en su lugar y devuelve None; lista = random.shuffle(lista) pierde la lista |
Ejercicio de depuración |
9. 📋 Matriz de trazabilidad
| Contenido original | Archivo de origen | Concepto desarrollado | Ejercicio original | Reto adicional | Proyecto relacionado |
|---|---|---|---|---|---|
| Filtración de contraseñas, haveibeenpwned | 037 |
Sección 0 | — | — | Sección 4 |
for con listas, dentro y fuera del bucle, Thonny |
038 |
Tema 1 | Ejercicio posterior (mencionado, no suministrado) | Retos 1–4 del Tema 1 | Proyectos 4 y 5 |
sum(), max() y su reconstrucción |
039 |
Tema 2 | Puntaje más alto | Retos 1–4 del Tema 2 (mínimo, segundo mayor) | Proyecto 5 |
range(), Gauss |
040 |
Tema 3 | Suma del 1 al 100. Reto de range posterior (mencionado, no suministrado) |
Retos 1–4 del Tema 3 (FizzBuzz) | Proyectos 4 y 6 |
| Generador de contraseñas, fácil y difícil | 041 |
Integración | Proyecto oficial | Depuración, secrets y extensiones |
Sección 4 |
| Perseverancia | 042 |
Sección 0 | — | — | — |
| (No existe en el curso original) | — | — | — | Analizador Saber 11 | Sección 5 |
| (No existe en el curso original) | — | — | — | ¿Es justo el azar? | Sección 6 |
10. 📦 Evidencias de aprendizaje del Día 5
- Generador de Contraseñas en sus dos niveles, con la tabla de pruebas.
- Puntaje más alto resuelto sin
max(), con su tabla de seguimiento. - FizzBuzz funcionando.
- Uno de los proyectos adicionales, con su tabla de resultados.
- Cuaderno de errores: desfase por uno en
range, acumulador reiniciado dentro del bucle,TypeError: 'int' object is not callable(por usarsumcomo variable) yshuffleque devuelveNone.