Lección 4: Bucles que recuerdan
Construye en Python el patrón «Juego del caos» y aprende por el camino:
- un bucle que lleva su estado de un paso al siguiente
- números enteros aleatorios con rng.integers
- un bucle while para una condición
- arrays de puntos y slicing
- np.column_stack
Míralo primero
Se reproduce desde YouTube tras hacer clic.
"""Chaos game: jump a part r of the way to a random corner of a polygon, again and again.
Run: python chaos-game.py (needs: pip install numpy matplotlib)
"""
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("dark_background")
corners, r, no_repeat = 3, 0.5, False # triangle, halfway: the Sierpinski triangle
steps = 60000
rng = np.random.default_rng()
angles = np.pi / 2 + 2 * np.pi * np.arange(corners) / corners
vertex = np.column_stack([np.cos(angles), np.sin(angles)])
points, chosen = np.zeros((steps, 2)), np.zeros(steps, dtype=int)
x, last = np.array([0.0, 0.0]), -1
for i in range(steps):
c = rng.integers(corners)
while no_repeat and c == last: # the restricted game: never the same corner twice
c = rng.integers(corners)
x = x + r * (vertex[c] - x) # the whole rule
points[i], chosen[i], last = x, c, c
plt.figure(figsize=(6, 6))
plt.scatter(points[20:, 0], points[20:, 1], s=0.3, c=chosen[20:], cmap="rainbow")
plt.axis("equal")
plt.axis("off")
plt.show()
# Try: corners, r = 5, 0.618 (a pentagon) or corners, no_repeat = 4, True (a square, restricted)
¿No tienes Python en este equipo? El cuaderno ejecuta el mismo script, los ejercicios y las respuestas en tu navegador, en Google Colab. El cuaderno está en inglés.
Línea a línea
vertex = np.column_stack([np.cos(angles), np.sin(angles)])Los vértices del polígono: sus valores x e y uno al lado del otro, una fila por vértice.
c = rng.integers(corners)Un número entero aleatorio de 0 a corners − 1: el vértice hacia el que saltar.
while no_repeat and c == last:El juego con restricción: mientras el nuevo vértice sea el último, vuelve a sortear.
x = x + r * (vertex[c] - x)La regla: avanza la parte r del camino del punto al vértice. Con r = 0.5, hasta la mitad.
points[i], chosen[i], last = x, c, cGuarda el punto y su vértice, y recuerda el vértice para el paso siguiente.
plt.scatter(points[20:, 0], points[20:, 1], s=0.3, c=chosen[20:], cmap="rainbow")Sáltate los 20 primeros puntos, que aún van de camino al fractal, y colorea el resto según su vértice.
Pruébalo tú
Dibuja un pentágono cuyas cinco copias apenas se toquen.
Pista
Cambia corners y r en una sola línea.
Respuesta
corners, r, no_repeat = 5, 0.618, False
¿Por qué el gráfico se salta los 20 primeros puntos?
Pista
¿Dónde empieza el punto?
Respuesta
Empieza en el centro, que no está en el fractal. Cada salto reduce a la mitad su distancia al fractal, así que tras 20 saltos está a menos de una millonésima (2⁻²⁰) del tamaño de la imagen.
Juega al juego del cuadrado con no_repeat y sin él. ¿Qué cambia?
Pista
corners = 4, r = 0.5.
Respuesta
Sin la restricción, los puntos simplemente llenan el cuadrado; con no_repeat = True aparece un fractal.
Cuestionario
Tarjetas de repaso
Lee el anverso, di el reverso para ti y luego abre la tarjeta.
rng.integers(n)
Un número entero aleatorio de 0 a n − 1.
while condition:
Repite su bloque mientras la condición sea True.
a[20:, 0]
Las filas de la 20 al final, columna 0, de un array 2D.
Contracción
Un paso que acerca entre sí dos puntos cualesquiera, como un salto a medio camino hacia un vértice.
Atractor
La forma sobre la que los pasos repetidos atraen a todos los puntos: aquí, el triángulo de Sierpiński.