Le paradoxe des anniversaires
D'après-toi si 30 personnes sont réunies dans une pièce, quelle est la probabilité que deux d'entre elles soient nées le même jour ?
Note ton estimation sur le côté car dans la suite de cette leçon nous allons modéliser cette situation. Et la réponse est peut-être surprenante !
- 1
Tout d'abord il nous faut une liste contenant les jours de naissance des 30 personnes. On modélise la par une liste d'entiers aléatoires pris entre 1 et 365.
Importe la fonctionrandint
du modulerandom
puis crée une variableanniversaires
dans l'éditeur. Assigne à cette variable une liste en compréhension qui génère 30 dates anniversaires aléatoires.Solution
On commence par importer la fonction
randint
du modulerandom
.Ensuite on définit la variable
anniversaires
, elle doit contenir une liste de 30 dates aléatoires. On construit la liste en compréhension en appelantrandint(1, 365)
trente fois :from random import randint anniversaires = [randint(1, 365) for i in range(30)]
- 2
J'ai défini pour toi une fonction
doublons
contenant la variableanniversaires
ainsi qu'une boucle for. Cette fonction n'est pas tout à fait correcte.Pour détecter si la liste
anniversaires
contient des doublons, l'idée est la suivante : pour chaque date de la listeanniversaires
, si cette date apparaît plus d'une fois dans la liste on revoie 1. Si aucun doublon n'est détecté on renvoie 0.Modifie la condition du
if
pour renvoyer 1 si ladate
apparaît plus d'une fois dans la liste. Tu peux utiliser la méthodecount
pour compter le nombre de fois qu'un élément apparaît dans une liste.Rappel : la méthode
count
s'utilise sur une liste en lui passant en argument la valeur à compter :>>> [1,3,1,5].count(1) 2
Solution
Pour chaque
date
de la liste, on compte le nombre de fois qu'elle apparaît en faisantanniversaires.count(date)
Il faut renvoyer 1 si ce nombre est supérieur à 1. Si aucun élément de la liste n'apparaît en double, c'est que la liste n'a pas de doublon. Dans ce cas on renvoie 0.
from random import randint def doublons(): anniversaires = [randint(1, 365) for i in range(30)] for date in anniversaires: if anniversaires.count(date) > 1: return 1 return 0
- 3
Appelle la fonction
doublons
plusieurs fois dans la console. Quelle semble être la probabilité d'avoir des doubles ?Solution
On appelle la fonction
doublons
dans la console. Les probabilités de faire 0 ou 1 semblent assez équilibrées.>>> doublons() 0 >>> doublons() 1
- 4
Pour obtenir la probabilité d'avoir deux personnes ayant le même anniversaires, on va faire une moyenne des résultats de la fonction
doublons
L'idée est la suivante : créer une liste en compréhension qui appelle la fonction
doublons
1000 fois. Chacun des éléments de cette liste est donc 0 ou 1 et on obtient facilement la moyenne en s'aidant de la fonctionsum
Ajoute dans l'éditeur une variable
p
en dehors de la fonctiondoublons
qui calcule la probabilité avec la méthode précédente. Puis affiche cette probabilité à l'aide d'unprint
Solution
Pour calculer la valeur de la variable
p
il nous faut tout d'abord une liste de 1000 éléments qui correspondent aux résultats de la fonctiondoublons
On obtient cette liste en compréhension en faisant
[doublons() for i in range(1000)]
Il nous reste à calculer la moyenne de cette liste à l'aide de la fonction
sum
, sans oublier de diviser par 1000.On assigne le résultat à la variable
p
qu'on affiche ensuite à l'aide d'unprint
from random import randint def doublons(): anniversaires = [randint(1, 365) for i in range(30)] for date in anniversaires: if anniversaires.count(date) > 1: return 1 return 0 p = sum([doublons() for i in range(1000)]) / 1000 print(p)
- 5
Ce résultat nous interroge : à partir de quelle taille de groupe a-t-on 50% de chances d'avoir des anniversaires le même jour ?
Dans un groupe de 1 personne la probabilité est 0 et dans un groupe de 366 personnes la probabilité est 1 (il n'y a que 365 jours par an). Comment évolue cette probabilité ? Nous allons faire un graphique pour la représenter.
Il faudrait faire le calcul de la question précédente pour chaque taille de groupe entre 1 et 366.
Pour commencer, modifie la fonction
doublons
pour qu'elle prenne un argument correspondant à la taille du groupe. Modifie en conséquence le calcul dep
pour que la probabilité obtenue corresponde au cas du groupe de 30 personnes.Solution
Il faut modifier l'en tête de la fonction
doublons
que l'on fait dépendre d'un argumentn
, ainsi que la variableanniversaires
qui doit contenirn
dates.On adapte ensuite le calcul de
p
pour appeler la fonctiondoublons
avec l'argument 30from random import randint def doublons(n): anniversaires = [randint(1, 365) for i in range(n)] for date in anniversaires: if anniversaires.count(date) > 1: return 1 return 0 p = sum([doublons(30) for i in range(1000)]) / 1000 print(p)
- 6
Pour faire la représentation graphique il nous faut une liste d'abscisses
X
qui correspond aux différentes tailles de groupes et une liste d'ordonnéesY
qui correspond aux probabilités que des gens aient leurs anniversaires le même jour pour chacune des tailles de groupe.Pour t'aider j'ai transformé le calcul de
p
en une fonction. Elle prend en argument le nombre de personnes dans le groupe et renvoie la probabilité que deux personnes aient leur anniversaire le même jour pour un groupe de la taille donnée.Défini une liste
X
de nombres allant de 1 à 70, qui correspond aux différentes tailles de groupes possibles (il n'est pas utile d'aller jusqu'à 365). Défini ensuite une listeY
qui calcule la probabilitép
d'avoir des anniversaires le même jour pour chacune de ces tailles de groupe.Solution
Pour définir
X
le plus simple est de convertir en liste une séquence renvoyée parrange
à l'aide de la fonctionlist
On définit
Y
en compréhension en calculant la probabilitép
pour chacune des tailles de groupes de la listeX
.from random import randint import matplotlib.pyplot as plt def doublons(n): anniversaires = [randint(1, 365) for i in range(n)] for date in anniversaires: if anniversaires.count(date) > 1: return 1 return 0 def p(n): return sum([doublons(n) for i in range(1000)]) / 1000 X = list(range(1, 71)) Y = [p(x) for x in X]
- 7
Il ne reste plus qu'à faire le graphique à l'aide du module
pyplot
de la librairie matplotlib. J'ai déjà importépyplot
sous l'aliasplt
Utilise les fonctions
plot
etshow
du modulepyplot
pour voir comment évolue la probabilité que deux personnes aient leur anniversaire le même jour en fonction de la taille du groupe.Solution
On trace le graphique à l'aide de la fonction
plot
. Pour obtenir des points rouges on peut passe l'option'r.'
dans l'appel de la fonctionplot
La fonction
show
nous affiche le graphique.from random import randint import matplotlib.pyplot as plt def doublons(n): anniversaires = [randint(1, 365) for i in range(n)] for date in anniversaires: if anniversaires.count(date) > 1: return 1 return 0 def p(n): return sum([doublons(n) for i in range(1000)]) / 1000 X = list(range(1, 71)) Y = [p(x) for x in X] plt.plot(X, Y, "b.") plt.show()
Bonus : tu peux modifier la liste X
pour qu'elle ne contienne que des tailles de groupes
entre 20 et 30 et ainsi mieux voir pour quelle taille de groupe la probabilité est 1/2.
Cette approche numérique est très puissante et nous permet d'obtenir une bonne intuition des phénomènes en modélisant les situations.