Leçon 3 : Hasard et comptage
Construis en Python le motif « Planche de Galton » et apprends en chemin :
- des nombres aléatoires avec np.random.default_rng
- True et False comptés comme 1 et 0
- compter avec np.bincount
- une liste en compréhension
- une simulation vérifiée avec une formule
Regarde-le d’abord
Lecture depuis YouTube après un clic.
"""Galton board: every ball goes left or right at random at each of 12 rows of pegs.
Run: python galton-board.py (needs: pip install numpy matplotlib)
"""
from math import comb
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("dark_background")
rows, balls, p = 12, 5000, 0.5 # p: the chance of bouncing right
rng = np.random.default_rng()
bins = (rng.random((balls, rows)) < p).sum(axis=1) # a ball's bin = how often it went right
counts = np.bincount(bins, minlength=rows + 1)
k = np.arange(rows + 1)
expected = [balls * comb(rows, i) * p**i * (1 - p) ** (rows - i) for i in k] # the binomial curve
plt.figure(figsize=(7, 4))
plt.bar(k, counts, color="#5eead4", label="balls")
plt.xlabel("bin = times the ball went right")
plt.plot(k, expected, color="white", label="C(n, k) p^k (1-p)^(n-k)")
plt.legend()
plt.show()
# Try: p = 0.65 tilts the board; rows = 24 makes the bell narrower for its width
Pas de Python sur cet ordinateur ? Le notebook exécute le même script, les exercices et les réponses dans ton navigateur, sur Google Colab. Le notebook est en anglais.
Ligne par ligne
rng = np.random.default_rng()Le générateur de nombres aléatoires de numpy. Donne-lui un nombre, default_rng(1), et chaque exécution donne les mêmes nombres « aléatoires ».
bins = (rng.random((balls, rows)) < p).sum(axis=1)Un tableau de 5 000 × 12 nombres aléatoires entre 0 et 1. Chacun en dessous de p vaut True, un rebond vers la droite ; additionner une ligne compte ses True, ce qui donne la case de la bille.
counts = np.bincount(bins, minlength=rows + 1)Combien de billes sont tombées dans chaque case de 0 à 12 ; minlength garantit que les cases vides des bords comptent pour 0.
expected = [balls * comb(rows, i) * p**i * (1 - p) ** (rows - i) for i in k]Une liste en compréhension : la formule binomiale pour chaque case i, multipliée par le nombre de billes.
plt.bar(k, counts, color="#5eead4", label="balls")Une barre par case. La ligne blanche tracée ensuite est la formule, pour comparer.
À toi de jouer
Lance le script deux fois. Les barres sont-elles les mêmes ? Puis fais que chaque exécution soit identique.
Indice
Donne un nombre à default_rng.
Réponse
Les barres changent un peu à chaque fois. rng = np.random.default_rng(1) donne la même exécution à chaque fois.
Combien de billes sur 5 000 devraient tomber dans la case du centre avec 12 rangées ?
Indice
La part de la case du centre est comb(12, 6) / 2**12.
Réponse
5000 × 924 ÷ 4096 ≈ 1128.
Penche la planche avec p = 0.65. Où est maintenant le centre de la cloche ?
Indice
Le centre est rows · p.
Réponse
12 × 0,65 = 7,8, donc le pic se déplace vers les cases 7 et 8.
Quiz
Cartes mémoire
Lis le recto, dis-toi le verso, puis retourne la carte.
np.random.default_rng(seed)
Un générateur de nombres aléatoires ; la même graine donne les mêmes nombres.
array < 0.5
Un tableau de True et de False ; True compte pour 1 quand on additionne.
np.bincount(xs)
Combien de fois chaque nombre entier 0, 1, 2, … apparaît dans xs.
[f(i) for i in k]
Une liste en compréhension : une nouvelle liste où f est appliquée à chaque élément de k.
comb(n, k)
Le nombre de façons de choisir k objets parmi n : math.comb(12, 6) vaut 924.