Saltar al contenido
Volver al inicio 100 Días de Código en Python — Día 4: Aleatoriedad y Listas

100 Días de Código en Python — Día 4: Aleatoriedad y Listas

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 4.

Este tutorial es una adaptación pedagógica del Día 4. 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
  2. El módulo random y los módulos en Python
  3. Listas: índices, modificación y append()
  4. IndexError y listas anidadas
  5. 🚀 Proyecto del día: Piedra, Papel o Tijera
  6. 🌟 Proyecto extra: Sorteo de la Semana de la Ciencia
  7. 🏆 Proyecto integrador del Día 4: Piedra, Papel, Tijera, Lagarto, Spock
  8. 🤖 Programar con apoyo de IA
  9. 🛠️ Correcciones técnicas al material original
  10. 📋 Matriz de trazabilidad
  11. 📦 Evidencias de aprendizaje del Día 4

0. Antes de empezar

(Fuente: 030 - Day 4 Goals- what we will make by the end of the day.md, 036 - Programming is like going to the Gym.md)

Hoy aprenderemos a hacer que el computador tome decisiones al azar y a guardar muchos datos relacionados en una sola variable. Con eso construiremos un juego de Piedra, Papel o Tijera contra el computador.

El mensaje motivacional del curso para hoy: programar es como ir al gimnasio. Nadie gana músculo viendo videos de ejercicio. Solo se aprende escribiendo código todos los días.

Prerequisito general: Días 1 a 3, en especial if/elif/else, operadores lógicos, int(input()) y subíndices de strings (Día 2, Tema 1).


1. El módulo random y los módulos en Python

(Fuente: 031 - Random Module.md)

Prerequisito: funciones (print, len, round), if/else (Día 3).

🎯 Objetivo de aprendizaje

  • Importar y usar el módulo random para generar números enteros y decimales al azar.
  • Explicar qué es un módulo y crear uno propio.
  • Consultar la documentación oficial para descubrir funciones nuevas.

🧠 ¿Qué aprenderemos?

  • Aleatoriedad y números pseudoaleatorios.
  • import, módulos y la notación con punto (random.randint).
  • random.randint(a, b), random.random() y random.uniform(a, b).

📖 Explicación conceptual

¿Por qué necesitamos aleatoriedad? Un Tetris en el que siempre cayera la misma secuencia de piezas no tendría gracia. Los juegos, los sorteos y las simulaciones necesitan imprevisibilidad.

Sin embargo, los computadores son deterministas: ante las mismas instrucciones hacen siempre lo mismo. Para simular el azar usan fórmulas matemáticas llamadas generadores de números pseudoaleatorios. Python usa uno llamado Mersenne Twister. No necesitamos programarlo: el equipo de Python ya lo hizo y lo dejó listo en el módulo random.

¿Qué es un módulo? Es un archivo de Python con código listo para reutilizar. Así como en una fábrica de carros un equipo arma el motor y otro las llantas, un programa grande se divide en módulos, cada uno responsable de una parte del trabajo.

Python
import random                 # 1. Importar el módulo

numero = random.randint(1, 10)  # 2. Usar una función: módulo.función()
print(numero)

Funciones principales

Función Qué devuelve ¿Incluye los extremos? Ejemplo
random.randint(a, b) Entero entre a y b Sí, incluye a y b randint(1, 6) es un dado
random.random() Decimal entre 0 y 1 Incluye 0, nunca 1 0.7314...
random.uniform(a, b) Decimal entre a y b Incluye a; incluir b depende del redondeo uniform(1, 10)

random.random() no recibe datos de entrada, pero igual necesita paréntesis vacíos () para ejecutarse. Para ampliar su rango se multiplica: random.random() * 10 da un decimal entre 0 y 10, sin incluir el 10.

Crear tu propio módulo

  1. Crea un archivo mi_modulo.py en la misma carpeta de tu programa.
  2. Escribe dentro numero_favorito = 3.1415.
  3. En tu archivo principal (por ejemplo main.py):
Python
import mi_modulo
print(mi_modulo.numero_favorito)   # 3.1415

Funciona exactamente igual que random: import + nombre del módulo + punto + lo que quieres usar.

🔎 Ejemplo explicado: lanzar un dado

Python
import random

dado = random.randint(1, 6)
print(f"Sacaste un {dado}")
if dado == 6:
    print("¡Vuelves a lanzar!")
  • Qué problema resuelve: simula un dado para un juego de mesa.
  • Por qué randint(1, 6): ambos extremos están incluidos, así que los resultados posibles son 1, 2, 3, 4, 5 y 6.
  • Resultado esperado: cambia en cada ejecución. Con muchas ejecuciones, cada cara debería salir más o menos 1 de cada 6 veces.

⚠️ Errores frecuentes

1. Olvidar el import

  • Qué ocurre: NameError: name 'random' is not defined.
  • Cómo solucionarlo: escribe import random al inicio del archivo.

2. Llamar a tu archivo random.py

  • Qué ocurre: errores extraños, como AttributeError: module 'random' has no attribute 'randint'.
  • Por qué ocurre: Python importa tu archivo en lugar del módulo oficial.
  • Cómo solucionarlo: nunca nombres tus archivos igual que un módulo de Python. Usa, por ejemplo, mi_dado.py.

3. Olvidar los paréntesis de random.random

  • Qué ocurre: print(random.random) muestra algo como <built-in method random ...> en lugar de un número.
  • Cómo solucionarlo: escribe random.random().

🛠️ Nota técnica: los números pseudoaleatorios de random sirven para juegos y simulaciones, pero no para seguridad (contraseñas o códigos de acceso), porque en principio son predecibles. Para eso Python ofrece el módulo secrets. Esto será importante en el proyecto del Día 5 (generador de contraseñas).

📝 Ejercicio original del curso: Cara o Sello

Enunciado: escribe un programa que imprima al azar "Cara" o "Sello" (en el original: Heads o Tails). Conceptos: random.randint, if/else.

🔍 Antes de programar

  • ¿Cuántos resultados posibles hay? ¿Qué rango de números necesitas para representarlos?
  • ¿Cómo asocias cada número con un resultado?
  • ¿Cómo compruebas que el programa es "justo"? (Pista: ejecútalo muchas veces y cuenta los resultados.)

Estrategia del curso: generar 0 o 1 con randint(0, 1). Si sale 0 es "Cara"; en cualquier otro caso, "Sello".

Retos adicionales (creados para esta adaptación)

🟢 Reto 1: Aplicación

Simula el lanzamiento de dos dados y muestra la suma.

🟡 Reto 2: Ampliación

Genera una temperatura aleatoria entre 14.0 y 32.0 °C con un decimal y recomienda la ropa adecuada con if/elif/else.

🟠 Reto 3: Desafío: moneda cargada

Simula una moneda "tramposa" que sale Cara el 70 % de las veces. Usa random.random() y una comparación. Explica en un comentario por qué funciona.

🔴 Reto 4: Pensamiento computacional: adivina el número (una oportunidad)

El computador "piensa" un número del 1 al 20. El usuario tiene un intento y el programa le dice si acertó, si se quedó corto o si se pasó, y por cuántos. Diseña el diagrama de flujo antes de programar. (En el Día 12 del curso construirás la versión completa, con varios intentos.)

🧩 Comprueba lo aprendido: Tema 1

  • Conceptual: ¿por qué los números del computador se llaman pseudoaleatorios?
  • Predicción: ¿qué valores puede producir random.randint(0, 2)? ¿Y int(random.random() * 3)?
  • Depuración: import Random seguido de print(random.randint(1, 10)) falla. ¿Por qué?
  • Creación: crea un módulo datos_colegio.py con el nombre de tu colegio y el año de fundación, e imprímelos desde otro archivo.

Evidencia: código del Reto 4 con su diagrama de flujo.


2. Listas: índices, modificación y append()

(Fuentes: 032 - Understanding the Offset and Appending Items to Lists.md, 033 - Who will pay the bill-.md)

Prerequisito: subíndices de strings (Día 2, Tema 1), len() (Día 1).

🎯 Objetivo de aprendizaje

  • Crear listas y acceder a sus elementos con índices positivos y negativos.
  • Modificar elementos y agregar nuevos con append() y extend().
  • Combinar listas con random para elegir elementos al azar.

🧠 ¿Qué aprenderemos?

  • ¿Qué es una estructura de datos?
  • Sintaxis de las listas, índices como desplazamiento (offset).
  • Modificar, append(), extend(), random.choice().

📖 Explicación conceptual

¿Por qué listas? Una variable guarda un dato. Pero a veces los datos van juntos y tienen un orden: la fila de la cafetería, los estudiantes de un curso, los departamentos de Colombia. Crear departamento1, departamento2, …, departamento32 sería absurdo. Una lista los guarda todos en una sola variable, en orden.

Python
frutas = ["Cereza", "Manzana", "Pera"]
  • Se abre y se cierra con corchetes [ ].
  • Los elementos van separados por comas.
  • Pueden ser de cualquier tipo, incluso mezclados: ["Ana", 16, 1.62, True].

Índices como desplazamiento ¿Por qué el primer elemento está en la posición 0? El curso lo explica así: el índice no es "la posición", sino cuántos pasos te alejas del inicio. El primer elemento está justo al inicio: 0 pasos.

Python
departamentos = ["Amazonas", "Antioquia", "Arauca", "Atlántico"]
print(departamentos[0])    # Amazonas
print(departamentos[2])    # Arauca
print(departamentos[-1])   # Atlántico (el último)

Modificar un elemento

Python
departamentos[1] = "ANTIOQUIA"

Agregar elementos

Python
departamentos.append("Bolívar")               # agrega UN elemento al final
departamentos.extend(["Boyacá", "Caldas"])    # agrega VARIOS (otra lista) al final

Consejo del curso: no memorices todos los métodos de las listas. Consulta la documentación oficial (se abre en otra pestaña) para saber qué existe y búscalo cuando lo necesites. Programar es un examen a libro abierto.

Elegir al azar de una lista

Python
import random
ganador = random.choice(departamentos)

🔎 Ejemplo explicado: la fila de la cafetería

Python
fila = ["Sara", "Tomás", "Luisa"]
print(f"Primero en la fila: {fila[0]}")
fila.append("Mateo")
print(f"Acaba de llegar: {fila[-1]}")
print(f"Personas en la fila: {len(fila)}")
  • Qué problema resuelve: representa una fila que conserva el orden de llegada.
  • Resultado esperado: Primero en la fila: Sara, Acaba de llegar: Mateo y Personas en la fila: 4.
  • Observa: len() también funciona con listas (Día 2: len() acepta secuencias).

⚠️ Errores frecuentes

1. Usar paréntesis en vez de corchetes para el índice

  • Qué ocurre: fila(0) produce TypeError: 'list' object is not callable.
  • Cómo solucionarlo: usa fila[0].

2. Confundir append con extend

  • Qué ocurre: lista.append(["a", "b"]) agrega una lista dentro de la lista, no dos elementos.
  • Cómo solucionarlo: para agregar varios elementos usa extend.

3. Olvidar las comas entre los elementos

  • Qué ocurre: ["Sara" "Tomás"] no da error, pero ¡crea un solo elemento: "SaraTomás"! Python une automáticamente dos strings escritos uno junto al otro.
  • Cómo identificarlo: revisa con len() cuántos elementos tiene la lista realmente.

📝 Ejercicio original del curso: ¿Quién paga la cuenta?

Contexto del curso: en el distrito financiero de Londres, algunos grupos de banqueros deciden quién paga la cuenta de todos sacando al azar una tarjeta de presentación de un recipiente. Enunciado: dada una lista de amigos, imprime al azar el nombre de quien paga. Conceptos: listas, índices, random.

🔍 Antes de programar

  • ¿Qué índices son válidos en una lista de 5 nombres?
  • ¿Puedes resolverlo solo con lo que ya sabes (randint + índice)?
  • ¿Existirá una función hecha para esto? ¿Cómo la buscarías?

El curso presenta dos soluciones válidas:

Opción Idea Ventaja
1. Buscar en la documentación random.choice(amigos) Menos código y más legible
2. Usar lo que ya sabes Índice aleatorio con randint y luego amigos[indice] Demuestra comprensión de los índices

🛠️ Nota técnica: la solución 2 del curso usa randint(0, 4), un número fijo que solo funciona con exactamente 5 amigos. Es más robusto escribir randint(0, len(amigos) - 1), que se adapta a listas de cualquier tamaño.

Retos adicionales (creados para esta adaptación)

🟢 Reto 1: Aplicación

Crea una lista con 5 canciones y muestra la primera, la última y una al azar.

🟡 Reto 2: Ampliación

Pide al usuario tres nombres, uno por uno, agrégalos con append() a una lista vacía [] y muestra la lista final y su tamaño.

🟠 Reto 3: Desafío: menú del día

Con tres listas (sopas, platos fuertes y bebidas), genera al azar un menú completo. Luego permite que el usuario cambie el plato fuerte por otro al azar si escribe "otro".

🔴 Reto 4: Pensamiento computacional: orden del día

El curso tiene 6 exposiciones y el profesor quiere sortear quién expone primero y quién expone último, sin que sea la misma persona. Sin usar ciclos, ¿cómo lo garantizas? Investiga en la documentación el método remove() o random.sample(), elige una estrategia y justifícala.

🧩 Comprueba lo aprendido: Tema 2

  • Conceptual: explica con tus palabras por qué el primer índice es 0.
  • Predicción: con x = [10, 20, 30, 40], ¿qué valen x[1], x[-2] y len(x)? ¿Qué queda en x después de x[0] = 5 y x.append(50)?
  • Depuración: colores = ["rojo", "azul" "verde"] y luego print(colores[2]) produce un error. Explica por qué.
  • Creación: una lista de 4 frases motivacionales y un programa que muestre una al azar cada vez que se ejecute.

Evidencia: solución de "¿Quién paga la cuenta?" con las dos estrategias.


3. IndexError y listas anidadas

(Fuente: 034 - IndexErrors and Working with Nested Lists.md)

Prerequisito: Tema 2.

🎯 Objetivo de aprendizaje

  • Diagnosticar y corregir un IndexError, incluido el error de "desfase por uno" (off-by-one).
  • Crear listas dentro de listas y acceder a sus elementos con dos índices.

📖 Explicación conceptual

IndexError: list index out of range Aparece cuando pides un índice que no existe. En una lista de 50 elementos, el último está en el índice 49, no en el 50.

Python
estados = [...]                        # 50 estados
numero_de_estados = len(estados)       # 50
print(estados[numero_de_estados])      # ❌ IndexError
print(estados[numero_de_estados - 1])  # ✅ el último

Este es el error de desfase por uno (off-by-one): te pasas por un solo lugar. Es de los errores más comunes de la programación.

Listas anidadas Una lista puede contener otras listas. El curso usa la "Docena Sucia" (Dirty Dozen), un listado del Environmental Working Group con las frutas y verduras que tienen más residuos de pesticidas:

Python
frutas = ["Fresas", "Espinacas", "Kale", "Nectarinas", "Manzanas", "Uvas", "Duraznos", "Cerezas", "Peras"]
verduras = ["Tomates", "Apio", "Papas"]

docena_sucia = [frutas, verduras]
print(docena_sucia)
# [['Fresas', ..., 'Peras'], ['Tomates', 'Apio', 'Papas']]

Los dos corchetes al inicio y al final muestran que es una lista de listas.

Acceder a un elemento de una lista anidada (ampliación de esta adaptación):

Python
print(docena_sucia[1])      # ['Tomates', 'Apio', 'Papas']  → la sublista
print(docena_sucia[1][1])   # Apio → primero la sublista, luego el elemento

Lee docena_sucia[1][1] de izquierda a derecha: "de docena_sucia, toma el elemento 1 (verduras), y de ahí toma el elemento 1 (Apio)".

🛠️ Nota: el curso califica de "fruta" a las espinacas, el kale y otros vegetales, porque así están agrupados en la lista del ejemplo. Para programar esto no importa, pero es un buen momento para revisar críticamente cómo están clasificados los datos.

🔎 Ejemplo explicado: horario escolar

Python
horario = [
    ["Matemáticas", "Español", "Inglés"],      # lunes
    ["Tecnología", "Física", "Educación Física"],  # martes
]
print(f"El martes a primera hora tienes {horario[1][0]}")
  • Resultado esperado: El martes a primera hora tienes Tecnología.
  • Por qué es útil: los datos quedan organizados como una tabla de filas (días) y columnas (horas).

⚠️ Errores frecuentes

  • Usar len(lista) como índice → IndexError. El último índice válido es len(lista) - 1.
  • Invertir el orden de los índices anidados: horario[0][1] y horario[1][0] son elementos distintos.
  • Usar un índice doble en una lista simple: frutas[0][0] no da error, pero devuelve "F", ¡la primera letra del string! Revisa qué tipo de dato estás indexando.

Retos adicionales (creados para esta adaptación)

(El archivo 034 no propone un ejercicio propio; estos retos refuerzan sus conceptos.)

🟢 Reto 1: Aplicación

Con la docena_sucia, imprime la última fruta y la primera verdura.

🟡 Reto 2: Ampliación

Agrega una tercera sublista con granos (por ejemplo, arroz y fríjol) usando append() y muestra cuántas categorías tiene ahora la lista.

🟠 Reto 3: Desafío: el mapa del tesoro

Crea una cuadrícula de 3 × 3 con tres listas de "⬜". Pide al usuario una posición de dos dígitos (por ejemplo 21: columna 2, fila 1), marca esa casilla con "X" y muestra el mapa, una fila por línea. (Pista: posicion[0] es la columna como texto. Conviértela y réstale 1.)

🔴 Reto 4: Pensamiento computacional

Diseña una estructura de datos con listas anidadas para guardar las notas de 3 estudiantes en 3 materias. Escribe el código que imprima la nota del segundo estudiante en la tercera materia y el promedio del primer estudiante. Justifica en un comentario por qué organizaste los datos así y no al revés.

🧩 Comprueba lo aprendido: Tema 3

  • Predicción: con m = [[1, 2], [3, 4], [5, 6]], ¿qué valen m[2][0], m[-1][-1] y len(m)? ¿Qué pasa con m[3][0]?
  • Depuración: el código print(nombres[len(nombres)]) debería mostrar el último nombre. Corrígelo de dos formas.

Evidencia: Reto 3 (mapa del tesoro) funcionando con al menos tres posiciones diferentes.


4. 🚀 Proyecto del día: Piedra, Papel o Tijera

(Fuente: 035 - Day 4 Project- Rock Paper Scissors.md, proyecto oficial del curso original)

Problema

Construir un juego de Piedra, Papel o Tijera en el que el usuario juega una ronda contra el computador.

Contexto

Las reglas son: la piedra le gana a la tijera, la tijera le gana al papel y el papel le gana a la piedra. Si ambos eligen lo mismo, es empate. El curso incluso cita a la World Rock Paper Scissors Association como referencia de las reglas oficiales.

Objetivo

El usuario elige escribiendo 0 (piedra), 1 (papel) o 2 (tijera). El computador elige al azar. El programa muestra las dos elecciones con arte ASCII y anuncia el resultado.

Requisitos funcionales

  1. Pedir la elección del usuario (0, 1 o 2), con el cursor en una línea nueva.
  2. Generar al azar la elección del computador.
  3. Mostrar ambas elecciones con su dibujo ASCII.
  4. Anunciar "Ganaste", "Perdiste" o "Empate".
  5. Si el usuario escribe un número inválido, mostrar "Escribiste un número inválido. Pierdes" sin que el programa se bloquee.

Restricciones técnicas

random, listas, if/elif/else, operadores lógicos e int(input()). El código inicial del curso trae el arte ASCII de cada figura guardado en las variables rock, paper y scissors. Ese archivo no está incluido entre los materiales suministrados, así que puedes buscar tus propios dibujos o crearlos.

🔍 Antes de programar

  • Divide el problema (recomendación del curso): primero la lógica con números, después los dibujos.
  • Construye la tabla de los 9 casos (3 × 3) posibles: ¿quién gana en cada uno?
  • ¿Qué pasa si el usuario escribe 5, y en qué momento hay que revisarlo?

Construcción paso a paso (siguiendo la solución del curso)

Versión 1: las elecciones. Pide la elección del usuario (con int()) y genera la del computador con random.randint(0, 2). Imprime el número que eligió el computador para probar.

El curso muestra el error que aparece al olvidar int(): '>' not supported between instances of 'int' and 'str'.

Versión 2: la lógica. El curso llega a la solución por prueba y error, probando casos y agregando condiciones cuando algo falla. Estas son las condiciones a las que llega:

Situación Resultado
El usuario escribe un número ≥ 3 o < 0 Número inválido, pierdes
Ambas elecciones son iguales Empate
Usuario 0 (piedra) y computador 2 (tijera) Ganas (excepción a la regla general)
Computador 0 (piedra) y usuario 2 (tijera) Pierdes (excepción a la regla general)
Elección del computador > elección del usuario Pierdes
Elección del usuario > elección del computador Ganas

Lección clave del curso sobre el ORDEN: al principio, la validación del número inválido estaba al final del if/elif, y un número como 456 "ganaba" porque lo atrapaba antes usuario > computador. La validación debe ir primero.

Versión 3: los dibujos. Guarda los tres dibujos en una lista en el mismo orden que los números: imagenes = [piedra, papel, tijera]. Así imagenes[eleccion_usuario] muestra el dibujo correcto sin más if. Muestra el dibujo del usuario solo si su número es válido, porque de lo contrario se produce un IndexError.

Alternativa válida (ampliación de esta adaptación, no aparece en el curso)

Con el operador módulo del Día 3 la lógica se reduce a una sola regla:

Python
if eleccion_usuario == eleccion_computador:
    resultado = "Empate"
elif (eleccion_usuario - eleccion_computador) % 3 == 1:
    resultado = "Ganaste"
else:
    resultado = "Perdiste"

Verifica con la tabla de 9 casos que ambas versiones dan el mismo resultado. Discute: ¿cuál es más fácil de entender? ¿Cuál es más fácil de extender a más figuras?

Pruebas

Usuario Computador Resultado esperado
0 0 Empate
0 2 Ganaste
2 0 Perdiste
1 0 Ganaste
1 2 Perdiste
7 cualquiera Número inválido, sin que el programa se bloquee
-1 cualquiera Número inválido (ojo: imagenes[-1] no da error, pero mostraría la tijera)

💡 Como el computador elige al azar, para probar un caso específico puedes fijar temporalmente eleccion_computador = 2 y luego volver a la versión aleatoria.

🧪 Prueba y depuración

Este código tiene tres errores de lógica. Encuéntralos con la tabla de pruebas:

Python
if eleccion_usuario == eleccion_computador:
    print("Empate")
elif eleccion_computador > eleccion_usuario:
    print("Perdiste")
elif eleccion_usuario == 0 and eleccion_computador == 2:
    print("Ganaste")
elif eleccion_usuario > eleccion_computador:
    print("Ganaste")
elif eleccion_usuario >= 3 or eleccion_usuario < 0:
    print("Número inválido")

⭐ Extensión del proyecto

  • Aceptar también que el usuario escriba "piedra", "papel" o "tijera". (Investiga el método lista.index().)
  • Mostrar el nombre de cada elección además del dibujo, usando una segunda lista nombres = ["Piedra", "Papel", "Tijera"].

5. 🌟 Proyecto extra: Sorteo de la Semana de la Ciencia

Situación

En la Semana de la Ciencia, cada curso debe presentar un experimento. Para que sea justo, el docente quiere sortear el tema, el estudiante líder y el orden de presentación del curso.

Objetivo

Construir un programa de sorteo que:

  1. Tenga una lista de temas (por ejemplo, energía solar, reciclaje, volcanes, circuitos y fotosíntesis) y una lista con los estudiantes del grupo.
  2. Permita agregar un estudiante nuevo con append() antes del sorteo.
  3. Sortee el tema y el líder.
  4. Sortee un colíder que no sea el mismo líder. (Decide: ¿remove(), random.sample() o un índice calculado?)
  5. Muestre un "acta del sorteo" con f-strings.

Decisiones que debes tomar

  • ¿Cómo evitas que el líder y el colíder sean la misma persona sin usar ciclos?
  • ¿Qué pasa si la lista de estudiantes tiene una sola persona? ¿Cómo lo detectas con len() y un if?

Casos de prueba

  • Lista de 1 estudiante → mensaje: "Se necesitan al menos 2 estudiantes".
  • Lista de 5 estudiantes → líder y colíder diferentes. Ejecuta 10 veces y verifica que nunca se repitan.

⭐ Extensión

Organiza los grupos de todo el grado como una lista anidada ([["10A", ...], ["10B", ...]]), sortea primero el curso y luego un estudiante de ese curso.


6. 🏆 Proyecto integrador del Día 4: Piedra, Papel, Tijera, Lagarto, Spock

Proyecto integrador creado para esta adaptación. Combina listas, random, validación, operadores lógicos, módulo (Día 3) y f-strings (Día 2).

Situación problema

La versión "extendida" del juego, popularizada por una serie de televisión, agrega dos figuras: Lagarto y Spock. Con 5 figuras hay 25 combinaciones posibles, y resolverlas con if una por una es largo y propenso a errores.

Reglas: la tijera corta el papel, el papel cubre la piedra, la piedra aplasta al lagarto, el lagarto envenena a Spock, Spock rompe la tijera, la tijera decapita al lagarto, el lagarto se come el papel, el papel desautoriza a Spock, Spock vaporiza la piedra y la piedra aplasta la tijera.

Pregunta orientadora

¿Cómo representar las reglas de un juego de forma que el programa sea corto, correcto y fácil de verificar?

Requerimientos

  1. Una lista figuras con los 5 nombres.
  2. Pedir la elección del usuario como número (0 a 4) y validarla antes de cualquier otra cosa.
  3. Elegir la figura del computador con random.
  4. Mostrar ambas elecciones por su nombre, usando la lista.
  5. Determinar el resultado. Reto de diseño: si ordenas las figuras como ["Piedra", "Spock", "Papel", "Lagarto", "Tijera"], existe una regla con % 5 que decide quién gana. Descúbrela en papel analizando la tabla de 25 casos. (Pista: compárala con la regla % 3 del proyecto del día.)
  6. Mostrar por qué ganó alguien. Por ejemplo: "Spock vaporiza la piedra". (Decide cómo guardar esas frases.)

Restricciones técnicas

Conceptos de los Días 1 a 4. Sin ciclos.

Etapas de desarrollo

  1. Tabla de 25 casos en papel.
  2. Descubrir y verificar la regla con %.
  3. Programar la validación, las elecciones y el resultado.
  4. Agregar las frases explicativas.
  5. Probar con un valor fijo del computador y luego volver al azar.

Entregables

Código funcional, tabla de 25 casos y explicación escrita de la regla con %.

Criterios técnicos

  • Los 25 casos se resuelven correctamente.
  • Las entradas inválidas (5, -1, 10) no bloquean el programa ni muestran una figura.
  • El código usa listas en lugar de repetir if por cada figura.

Posibles extensiones

Agrega dibujos ASCII o emojis para cada figura. Investiga cómo se generalizaría la regla a 7 figuras.


7. 🤖 Programar con apoyo de IA

El curso insiste en dos habilidades complementarias: buscar (como hallar random.choice en la documentación) y deducir con lo que ya sabes (como armar un índice aleatorio con randint). Una IA puede darte la primera respuesta rápido, pero la segunda habilidad es la que te permite comprobar si esa respuesta es correcta.

Actividad: auditar una solución. Pide a una IA la lógica de Piedra, Papel o Tijera. Luego:

  1. Pasa su código por tu tabla de 9 casos más los casos inválidos (7 y -1).
  2. Verifica si valida la entrada antes de usarla como índice.
  3. Si usa algo que no conoces (por ejemplo, diccionarios, que verás en el Día 9), búscalo en la documentación y escribe qué hace.
  4. Escribe un informe corto: ¿pasó todas las pruebas?, ¿qué corregiste?

8. 🛠️ Correcciones técnicas al material original

Archivo Afirmación en la transcripción Qué ocurre realmente Tratamiento
031 "random.random() siempre incluye 1 pero puede que nunca incluya 1" (frase confusa) Genera valores en el rango [0, 1): incluye 0 y nunca 1 Tabla del Tema 1
031 No advierte sobre la seguridad random no es apto para contraseñas ni seguridad; para eso existe secrets Nota técnica del Tema 1
032 estado2 == "Pennsylvania" al crear variables Es una comparación, no una asignación (error de dictado). Lo correcto es = Se usa =
033 randint(0, 4) con un número fijo Solo funciona con 5 elementos. Es mejor randint(0, len(lista) - 1) Nota técnica del Tema 2
035 "generar un número aleatorio entre 1 y 3" La solución usa 0 a 2, para que coincida con los índices de la lista Se usa 0 a 2
035 Validación con >= 3 or < 0 Correcta, pero imagenes[-1] no da error y mostraría la tijera; por eso la validación debe ir antes de mostrar los dibujos Casos de prueba del proyecto

9. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Objetivos: Piedra, Papel o Tijera 030 Sección 0 — — Sección 4
Aleatoriedad, random, módulos propios 031 Tema 1 Cara o Sello Retos 1–4 del Tema 1 (dado, moneda cargada, adivinar) Proyectos 4, 5 y 6
Listas, desplazamiento, modificación, append, extend 032 Tema 2 — (lección guiada) Retos 1–4 del Tema 2 Proyectos 4, 5 y 6
random.choice frente a índice aleatorio 033 Tema 2 ¿Quién paga la cuenta? (dos soluciones) Reto 4 del Tema 2 (orden de exposición) Proyecto 5
IndexError, desfase por uno, listas anidadas 034 Tema 3 — Retos 1–4 del Tema 3 (mapa del tesoro, notas) Proyecto 5 (extensión)
Piedra, Papel o Tijera 035 Integración Proyecto oficial completo Alternativa con %, depuración y extensiones Sección 4
Programar es como ir al gimnasio 036 Sección 0 — — —
(No existe en el curso original) — — — Sorteo de la Semana de la Ciencia Sección 5
(No existe en el curso original) — — — Piedra, Papel, Tijera, Lagarto, Spock Sección 6

10. 📦 Evidencias de aprendizaje del Día 4

  • Piedra, Papel o Tijera funcionando, con la tabla de 9 casos más los casos inválidos probados.
  • "¿Quién paga la cuenta?" resuelto con las dos estrategias del curso.
  • Mapa del tesoro (Reto 3 del Tema 3) funcionando.
  • Uno de los proyectos adicionales: el Sorteo o la versión Lagarto-Spock con su tabla de 25 casos.
  • Cuaderno de errores actualizado: IndexError (desfase por uno), AttributeError por llamar a un archivo igual que un módulo y TypeError: 'list' object is not callable.