Saltar al contenido
Volver al inicio 100 Días de Código en Python — Día 8: Funciones con Parámetros y Cifrado César

100 Días de Código en Python — Día 8: Funciones con Parámetros y Cifrado César

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 8.

Este tutorial adapta pedagógicamente el Día 8. 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

  1. Antes de empezar: mensajes secretos
  2. Funciones con entradas: parámetros y argumentos
  3. Varias entradas: argumentos posicionales y por palabra clave
  4. Cifrado César, parte 1: cifrar (index() y %)
  5. Cifrado César, parte 2: descifrar y unificar en una sola función
  6. Cifrado César, parte 3: caracteres especiales, repetir y depurar
  7. 🚀 Proyecto del día: el programa César completo
  8. 🌟 Proyecto extra: Rompe el código (ataque de fuerza bruta)
  9. 🏆 Proyecto integrador del Día 8: Cifrado de Vigenère
  10. 🤖 Programar con apoyo de IA
  11. 🛠️ Correcciones técnicas al material original
  12. 📋 Matriz de trazabilidad
  13. 📦 Evidencias de aprendizaje del Día 8

0. Antes de empezar: mensajes secretos

(Fuente: 060 - Day 8 Goals- what we will make by the end of the day.md, 066 - How You Can -Stay- Motivated.md)

Según la historia, Julio César enviaba sus mensajes militares desplazando cada letra un número fijo de posiciones en el alfabeto. Con un desplazamiento de 3, la A se convierte en D, la B en E, y así sucesivamente. Quien conoce el número puede deshacer el cambio. Hoy programaremos ese cifrado César. Para lograrlo, necesitamos funciones que reciban datos: el texto, el desplazamiento y si se debe cifrar o descifrar.

Mensaje de cierre del curso: en algún momento tu motivación va a bajar. Escribe por qué estás aprendiendo a programar y ponlo en un lugar visible.

Prerequisito general: funciones sin parámetros (Día 6), listas e índices (Día 4), % (Día 3) y bucles (Días 5 y 6).


1. Funciones con entradas: parámetros y argumentos

(Fuente: 061 - Functions with Inputs.md)

Prerequisito: definir y llamar funciones (Día 6).

🎯 Objetivo de aprendizaje

  • Definir funciones que reciben datos.
  • Distinguir entre parámetro y argumento.

📖 Explicación conceptual

Una función sin entradas hace siempre lo mismo:

Python
def saludar():
    print("Hola")
    print("¿Cómo estás?")
    print("¿Qué tal el clima?")

¿Y si quisiéramos saludar a cada persona por su nombre? Hay que darle a la función un dato de entrada:

Python
def saludar_con_nombre(nombre):     # nombre es el PARÁMETRO
    print(f"Hola {nombre}")
    print(f"¿Cómo estás, {nombre}?")

saludar_con_nombre("Angela")          # "Angela" es el ARGUMENTO
saludar_con_nombre("Jack Bauer")

Cuando se llama la función, Python hace algo equivalente a nombre = "Angela" dentro de la función.

Término Qué es En el ejemplo
Parámetro El nombre que recibe el dato dentro de la función nombre
Argumento El valor real que se envía al llamar la función "Angela"

Analogía del curso: una memoria USB. El computador (la función) es el mismo, pero muestra archivos distintos según la memoria (el argumento) que conectes.

En internet, a veces se usan "parámetro" y "argumento" como si fueran sinónimos. Lo importante es que tú conozcas la diferencia.

⚠️ Errores frecuentes

  • Llamar la función sin argumento: saludar_con_nombre() produce TypeError: missing 1 required positional argument: 'nombre'.
  • Enviar argumentos de más: saludar_con_nombre("Ana", "Luis") produce TypeError: takes 1 positional argument but 2 were given.
  • Usar el parámetro fuera de la función: print(nombre) fuera de ella produce NameError. El parámetro solo existe dentro de la función.

📝 Ejercicio original del curso: la función greet

Enunciado:

  1. Crea greet() con tres print() y llámala.
  2. Crea greet_with_name(name) que use el nombre en los mensajes (con f-strings) y llámala con distintos nombres.

Antes de ejecutar: predice qué se imprimirá con greet_with_name("Angela").

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: mostrar_tabla(numero) imprime la tabla de multiplicar del número que recibe.
  • 🟡 Reto 2: dibujar_linea(largo) imprime una línea de - del largo indicado. Úsala para enmarcar un título.
  • 🟠 Reto 3: verificar_contrasena(clave) imprime si la clave es "débil" (menos de 8 caracteres) o "aceptable". Llámala con 3 claves distintas.
  • 🔴 Reto 4: revisa tus proyectos de los días anteriores (la Caja Registradora del Día 6 o el Ahorcado del Día 7) y encuentra un bloque de código que se repita con pequeñas variaciones. Conviértelo en una función con parámetro.

🧩 Comprueba lo aprendido: Tema 1

  • Conceptual: en def area(base, altura): y area(4, 5), señala los parámetros y los argumentos.
  • Predicción: ¿qué imprime este código?
Python
  def doble(x):
      print(x * 2)
  doble(3)
  doble("ja")
  • Depuración: corrige def saludar(nombre): print(f"Hola {nombre}") seguido de la llamada saludar().

2. Varias entradas: argumentos posicionales y por palabra clave

(Fuente: 062 - Positional vs. Keyword Arguments.md)

🎯 Objetivo de aprendizaje

  • Definir funciones con varios parámetros.
  • Usar argumentos posicionales y argumentos por palabra clave (keyword arguments), y elegir el adecuado.

📖 Explicación conceptual

Python
def saludar_con(nombre, ubicacion):
    print(f"Hola {nombre}")
    print(f"¿Cómo es la vida en {ubicacion}?")

Argumentos posicionales. Se asignan por orden: el primer argumento va al primer parámetro, el segundo al segundo.

Python
saludar_con("Jack Bauer", "Nowhere")   # ✅
saludar_con("Nowhere", "Jack Bauer")   # ❌ "Hola Nowhere" / "¿Cómo es la vida en Jack Bauer?"

Argumentos por palabra clave. Se indica el parámetro al que va cada valor, así que el orden deja de importar:

Python
saludar_con(ubicacion="Londres", nombre="Angela")   # ✅ funciona igual
Tipo Ventaja Desventaja
Posicional Más corto Es fácil equivocarse con el orden
Por palabra clave Más claro y menos propenso a errores Las líneas quedan más largas

El curso recomienda usar tu criterio: con 1 o 2 parámetros obvios, los argumentos posicionales bastan; con muchos parámetros, o cuando el orden no es evidente, conviene usar palabras clave.

⚠️ Errores frecuentes

  • Poner un argumento posicional después de uno por palabra clave: saludar_con(nombre="Ana", "Cali") produce SyntaxError: positional argument follows keyword argument.
  • Escribir mal el nombre del parámetro: saludar_con(nombres="Ana", ubicacion="Cali") produce TypeError: got an unexpected keyword argument 'nombres'.

📝 Ejercicio original del curso: llamar con palabras clave

Enunciado: llama a greet_with(name, location) usando argumentos por palabra clave y comprueba que el resultado no cambia si inviertes el orden.

La lección termina remitiendo a "un ejercicio de codificación" en la lección siguiente. Su enunciado no está incluido entre los archivos suministrados.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: presentar(nombre, curso, edad). Llámala de las dos formas.
  • 🟡 Reto 2: calcular_imc(peso, estatura). Llámala con los argumentos invertidos por posición y explica el resultado absurdo. Luego corrígelo con palabras clave.
  • 🟠 Reto 3: precio_final(precio, descuento, iva) que imprime el precio con descuento e IVA. Escribe 3 llamadas y verifica los resultados a mano.
  • 🔴 Reto 4: investiga los valores por defecto (def saludar(nombre, saludo="Hola"):) en la documentación oficial. ¿Qué problema resuelven? Escribe un ejemplo propio.

3. Cifrado César, parte 1: cifrar

(Fuente: 063 - Caesar Cipher Part 1 - Encryption.md)

Prerequisito: Temas 1 y 2, % (Día 3) y listas (Día 4).

🎯 Objetivo de aprendizaje

  • Encontrar la posición de un elemento en una lista con .index().
  • Usar % para "dar la vuelta" al alfabeto.
  • Construir la función encrypt(original_text, shift_amount).

📖 Explicación conceptual

El método .index() devuelve la posición de un elemento en una lista:

Python
frutas = ["manzana", "pera", "naranja"]
frutas.index("pera")    # 1

El algoritmo, letra por letra. Ejemplo: "hello" con desplazamiento 2.

Letra alphabet.index(letra) + desplazamiento Nueva letra
h 7 9 j
e 4 6 g
l 11 13 n
l 11 13 n
o 14 16 q

Resultado: jgnnq.

El problema del final del alfabeto. Si ciframos z (posición 25) con desplazamiento 9, la nueva posición sería 34, que no existe: se produce IndexError. La solución del curso es usar el módulo con la longitud del alfabeto (26):

Python
posicion_desplazada %= len(alphabet)   # 34 % 26 = 8 → "i"

El residuo siempre queda entre 0 y 25. Es como un reloj: después de la última posición se vuelve a empezar desde la primera.

🛠️ Nota técnica: en el video, el módulo se explica con 25 ("34 % 25 = 9"). Pero el alfabeto tiene 26 letras y el código usa len(alphabet), que es 26: 34 % 26 = 8, que corresponde a la letra i. Es justo el resultado que el propio video anuncia ("debería darnos i"). Con 25 el resultado sería incorrecto.

Estructura de la solución del curso:

  1. def encrypt(original_text, shift_amount):
  2. Un acumulador cipher_text = "" fuera del for.
  3. Por cada letra: posición → posición + desplazamiento → % → letra nueva → acumular.
  4. Después del for: imprimir el resultado.
  5. Llamar la función con argumentos por palabra clave: encrypt(original_text=text, shift_amount=shift).

Consejo del curso: imprime los valores intermedios (posición, nueva posición, letra) mientras programas, para ver qué ocurre "entre bastidores".

📝 Ejercicio original del curso: TODO de la parte 1

  1. Crear encrypt con los parámetros original_text y shift_amount.
  2. Dentro de ella, desplazar cada letra hacia adelante e imprimir el texto cifrado.
  3. Llamarla con las entradas del usuario.
  4. Resolver el caso de z con desplazamiento 9 (IndexError).

El archivo inicial del curso (con la lista alphabet y las tres entradas) no está incluido entre los materiales suministrados. Crea alphabet = ["a", "b", ..., "z"]. Pista: list("abcdefghijklmnopqrstuvwxyz") crea esa misma lista en una sola línea.

🔍 Antes de programar

  • Cifra a mano hola con desplazamiento 3.
  • ¿Qué valor debe dar tu programa para xyz con desplazamiento 3? (Respuesta: abc.)
  • El curso menciona que hay varias soluciones para el problema del final del alfabeto. Piensa al menos en una distinta al módulo.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: cifra abc con desplazamiento 29. ¿Qué resultado da? ¿Por qué es igual al de desplazamiento 3?
  • 🟡 Reto 2: resuelve el problema del final del alfabeto sin %, usando un if. Compara ambas soluciones.
  • 🟠 Reto 3: haz que encrypt imprima una tabla de seguimiento como la de la explicación (letra, posición, nueva posición, letra nueva) antes del resultado final. (En el Día 10 aprenderás a hacer que una función devuelva su resultado en lugar de imprimirlo.)
  • 🔴 Reto 4: el alfabeto del curso no incluye la ñ. ¿Qué pasaría con "niño"? Modifica la lista para incluirla. ¿Qué cambia en el %? ¿Pueden comunicarse ahora dos personas que usen alfabetos distintos?

4. Cifrado César, parte 2: descifrar y unificar

(Fuente: 064 - Caesar Cipher Part 2 - Decryption.md)

🎯 Objetivo de aprendizaje

  • Construir decrypt e identificar que es casi igual a encrypt.
  • Eliminar el código repetido combinando ambas en una sola función caesar.

📖 Explicación conceptual

Descifrar es desplazar hacia atrás: posición - desplazamiento. El % también funciona con números negativos en Python: (0 - 2) % 26 da 24, que es la y. Así, descifrar a con 2 da y.

Código repetido → una sola función. encrypt y decrypt solo difieren en una operación: + o -. El curso aprovecha un truco matemático: sumar un número negativo es lo mismo que restar.

Python
def caesar(original_text, shift_amount, encode_or_decode):
    if encode_or_decode == "decode":
        shift_amount *= -1
    # ...el mismo bucle de encrypt, siempre con +

Cuidado con los nombres (sombreado de variables). Si el parámetro se llamara direction, igual que la variable global donde se guarda la respuesta del usuario, PyCharm advierte: "Shadows name 'direction' from outer scope". El código funciona, pero es confuso. Por eso el curso lo llama encode_or_decode. *(El ámbito o *scope* se estudia a fondo en el Día 12.)*

Truco del mensaje final. En inglés, encode + d = encoded y decode + d = decoded, así que el curso escribe f"Here is the {encode_or_decode}d result".

🛠️ Nota para la versión en español: ese truco depende del inglés. Con "codificar"/"decodificar" no funciona agregar una letra. Usa un if para elegir el mensaje, o nombra las opciones de modo que el truco funcione (por ejemplo "cifrado"/"descifrado", y escribe f"Resultado {modo}:").

📝 Ejercicio original del curso: TODO de la parte 2

  1. Crear decrypt(original_text, shift_amount).
  2. Desplazar cada letra hacia atrás e imprimir el resultado.
  3. Combinar ambas en caesar(original_text, shift_amount, encode_or_decode).

Recomendación del curso: hazlo en orden. No saltes al paso 3 sin entender cómo se diferencia decrypt de encrypt.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: comprueba que cifrar y luego descifrar con el mismo desplazamiento devuelve el texto original, con 5 palabras distintas.
  • 🟡 Reto 2: descifrar con desplazamiento n es lo mismo que cifrar con 26 - n. Verifícalo y explica por qué.
  • 🟠 Reto 3: reescribe caesar sin *= -1, usando if/else para sumar o restar. ¿Cuál versión es más legible?
  • 🔴 Reto 4: el ROT13 es un César con desplazamiento 13. ¿Por qué con ROT13 la misma operación sirve para cifrar y para descifrar? Demuéstralo con código.

5. Cifrado César, parte 3: caracteres especiales, repetir y depurar

(Fuente: 065 - Caesar Cipher Part 3 - Reorganising our Code.md)

🎯 Objetivo de aprendizaje

  • Conservar sin cambios los caracteres que no son letras (espacios, números, símbolos).
  • Repetir el programa con una bandera should_continue.
  • Encontrar un error mediante pruebas.

📖 Explicación conceptual

Caracteres especiales. Si el carácter no está en alphabet, se agrega tal cual:

Python
if letter not in alphabet:
    output_text += letter
else:
    # desplazar como antes

Otra opción que menciona el curso es agregar números y símbolos a la lista alphabet. Es más difícil, porque hay que prever todos los símbolos posibles.

Repetir el programa. El mismo patrón de bandera del Día 7:

Python
should_continue = True
while should_continue:
    # pedir datos y llamar caesar(...)
    restart = input("Escribe 'si' para continuar, o 'no' para salir:\n").lower()
    if restart == "no":
        should_continue = False
        print("Adiós")

🧪 El error que se encuentra probando (actividad central del curso)

El curso pide probar repetidamente hasta encontrar un error. Lo que ocurre:

  • Cifrar ab con desplazamiento 2 → cd ✅
  • Descifrar cd con desplazamiento 2 → se espera ab, pero da af ❌ (resultado verificado).

Causa: la línea shift_amount *= -1 quedó dentro del for. Entonces el signo se invierte en cada letra: la primera letra se desplaza hacia atrás, la segunda hacia adelante, la tercera otra vez hacia atrás…

Corrección: mover esa línea antes del for. Es otra vez el tema del Día 5: lo que debe pasar una sola vez va fuera del bucle.

📝 Ejercicio original del curso: TODO de la parte 3

  1. Importar e imprimir logo desde art.py (archivo no incluido entre los materiales: crea tu propio logo en arte ASCII).
  2. Conservar los números, los símbolos y los espacios.
  3. Preguntar si se quiere repetir el programa y salir con "no".

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: haz que el programa conserve las mayúsculas: Hola → Krod. (Pista: .isupper() y .lower()/.upper().)
  • 🟡 Reto 2: valida que el desplazamiento sea un número y que la opción sea exactamente "encode" o "decode". Si no, vuelve a pedirla con un while.
  • 🟠 Reto 3: muestra al final cuántos mensajes se procesaron en la sesión.
  • 🔴 Reto 4: diseña 5 casos de prueba que habrían detectado el error de *= -1 desde el principio. ¿Por qué un caso de una sola letra no lo detecta?

6. 🚀 Proyecto del día: el programa César completo

(Fuente: archivos 063–065, proyecto oficial del curso original)

Requisitos funcionales

  1. Mostrar un logo al inicio.
  2. Preguntar: encode o decode, el mensaje y el desplazamiento.
  3. Una sola función caesar(original_text, shift_amount, encode_or_decode).
  4. Conservar los caracteres que no están en el alfabeto.
  5. Soportar cualquier desplazamiento (incluidos los mayores de 26) gracias a %.
  6. Repetir hasta que el usuario escriba "no".

🔍 Antes de programar

  • ¿Qué partes van dentro de la función y cuáles fuera (entradas del usuario, bucle de repetición)?
  • ¿Qué instrucciones deben ejecutarse una sola vez por llamada y cuáles una vez por letra?

Pruebas

Modo Texto Desplazamiento Resultado esperado
encode hello 2 jgnnq
encode z 9 i
decode cd 2 ab
decode a 2 y
encode hola mundo 123! 3 krod pxqgr 123!
decode krod pxqgr 123! 3 hola mundo 123!
encode abc 29 def

⭐ Extensión del proyecto

  • Soportar mayúsculas y la ñ.
  • Mostrar el mensaje cifrado en bloques de 5 letras (como en la criptografía clásica).
  • Reflexión: ¿es seguro el cifrado César? (Pista: ¿cuántas claves posibles hay? Ver el proyecto extra.)

7. 🌟 Proyecto extra: Rompe el código

Situación

Interceptaste el mensaje khoor. Sabes que usa el cifrado César, pero no conoces el desplazamiento. Como solo hay 25 desplazamientos útiles, puedes probarlos todos: eso es un ataque de fuerza bruta.

Requisitos

  1. Reutilizar tu función caesar sin modificarla. Esa es una de las ventajas de tener funciones.
  2. Un bucle for con range(1, 26) que, para cada desplazamiento, imprima: Desplazamiento 3: hello.
  3. El usuario lee la lista e identifica el mensaje legible.

Resultado verificado: con khoor, el desplazamiento 3 da hello.

⭐ Extensión (pensamiento computacional)

¿Puede el programa adivinar solo cuál es el mensaje correcto? Idea: cuenta en cada resultado cuántas letras son vocales, o cuántas palabras aparecen en una pequeña lista de palabras comunes del español ("el", "la", "de", "que"…). Elige el desplazamiento con la puntuación más alta. Esta es la base del análisis de frecuencias, la técnica que se usó históricamente para romper cifrados.

Reflexión

Si romper el cifrado César es tan fácil, ¿por qué es importante estudiarlo? ¿Qué harías para hacerlo más difícil de romper? (Ver el proyecto integrador.)


8. 🏆 Proyecto integrador del Día 8: Cifrado de Vigenère

Proyecto integrador creado para esta adaptación. Es una versión más robusta del cifrado César. Integra funciones con varios parámetros, listas, index(), %, bucles y validación.

Situación problema

El cifrado César se rompe probando 25 claves. En el siglo XVI se popularizó el cifrado de Vigenère, que en lugar de un solo desplazamiento usa una palabra clave: cada letra de la clave indica un desplazamiento distinto (a = 0, b = 1, …, z = 25) y la clave se repite a lo largo del mensaje.

Ejemplo clásico (verificado): mensaje attackatdawn, clave lemon → lxfopvefrnhr.

Mensaje a t t a c k a t d a w n
Clave (se repite) l e m o n l e m o n l e
Desplazamiento 11 4 12 14 13 11 4 12 14 13 11 4
Resultado l x f o p v e f r n h r

Pregunta orientadora

¿Cómo reutilizar las ideas del César (posición, desplazamiento y %) para construir un cifrado mucho más difícil de romper?

Requerimientos

  1. Función vigenere(texto, clave, modo) que cifre y descifre.
  2. La posición en la clave se calcula con %: el carácter i del mensaje usa la letra de la clave en la posición i % len(clave).
  3. Decisión de diseño: ¿la clave avanza también con los espacios y símbolos o solo con las letras? Justifícala y documéntala en un comentario.
  4. Validar que la clave solo tenga letras.
  5. Menú que se repite, igual que en el César.

Etapas

  1. Recorrer el mensaje con un índice (for i in range(len(texto))) y mostrar la letra de la clave que le corresponde a cada posición.
  2. Cifrar.
  3. Descifrar (reutiliza el truco * -1 del César).
  4. Caracteres especiales y validación.

Entregables

Código funcional, tabla de pruebas y un párrafo que compare la seguridad del César con la de Vigenère.

Criterios técnicos

  • vigenere("attackatdawn", "lemon", "encode") produce lxfopvefrnhr.
  • Descifrar el resultado devuelve el texto original.
  • No se produce IndexError con claves más largas o más cortas que el mensaje.

Posibles extensiones

Investiga cómo se rompió Vigenère en el siglo XIX (el método Kasiski) y por qué hoy tampoco se considera seguro.


9. 🤖 Programar con apoyo de IA

El curso muestra el valor de probar para encontrar errores: el problema del *= -1 no se ve leyendo el código, sino ejecutando casos.

Actividad: entrega a una IA tu función caesar con el error (*= -1 dentro del for) y pregúntale si tiene algún error. Luego:

  1. ¿Lo encontró? ¿Lo explicó bien?
  2. Verifica su corrección con tu tabla de pruebas.
  3. Pídele también casos de prueba. ¿Incluye alguno de varias letras en modo decode? Ese es el que revela el error.

Pregunta de ética: una IA puede romper un cifrado César en segundos. ¿Qué significa eso para la seguridad de la información? ¿Qué cifrados usan hoy las aplicaciones de mensajería?


10. 🛠️ Correcciones técnicas al material original

Archivo Afirmación en la transcripción Qué ocurre realmente Tratamiento
063 El módulo se explica con 25 ("34 % 25 = 9") El alfabeto tiene 26 letras: 34 % 26 = 8 → i Nota técnica, Tema 3
063 index se llama "función incorporada" Es un método de las listas: lista.index(x) Tema 3
064 El truco {encode_or_decode}d Funciona solo en inglés Nota para la versión en español, Tema 4
065 El resultado erróneo "una f" El resultado verificado del error es af en lugar de ab Tema 5
063–065 Archivos iniciales (alphabet, art.py) No están incluidos entre los materiales suministrados Se pide crearlos
— Seguridad del cifrado César No es seguro: solo hay 25 claves útiles Proyecto extra

11. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Objetivos: cifrado César 060 Sección 0 — — Sección 6
Funciones con entradas, parámetro frente a argumento 061 Tema 1 greet y greet_with_name Retos 1–4 del Tema 1 Todos
Varias entradas, posicionales frente a palabra clave 062 Tema 2 Llamar con palabras clave. Ejercicio posterior (mencionado, no suministrado) Retos 1–4 del Tema 2 (valores por defecto) Secciones 6 y 8
Cifrar, index(), % 063 Tema 3 TODO 1–4 de la parte 1 Retos 1–4 del Tema 3 (ñ) Secciones 6, 7 y 8
Descifrar, unificar, sombreado de nombres 064 Tema 4 TODO 1–3 de la parte 2 Retos 1–4 del Tema 4 (ROT13) Secciones 6 y 8
Caracteres especiales, repetición, error de *= -1 065 Tema 5 TODO 1–3 de la parte 3 y búsqueda del error Retos 1–4 del Tema 5 Sección 6
Motivación 066 Sección 0 — — —
(No existe en el curso original) — — — Rompe el código (fuerza bruta) Sección 7
(No existe en el curso original) — — — Cifrado de Vigenère Sección 8

12. 📦 Evidencias de aprendizaje del Día 8

  • Programa César completo que pasa la tabla de 7 pruebas.
  • Explicación escrita, con tus palabras, del error de *= -1 y de por qué ocurre.
  • Tabla de parámetros y argumentos (Tema 1) y ejemplo del error por invertir argumentos posicionales (Reto 2 del Tema 2).
  • Proyecto extra (fuerza bruta) o integrador (Vigenère).
  • Cuaderno de errores: TypeError: missing required positional argument, SyntaxError: positional argument follows keyword argument, IndexError al final del alfabeto y la instrucción que debía ir fuera del bucle.