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 fonction
randintdu modulerandompuis crée une variableanniversairesdans 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
randintdu 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
doublonscontenant la variableanniversairesainsi qu'une boucle for. Cette fonction n'est pas tout à fait correcte.Pour détecter si la liste
anniversairescontient 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
ifpour renvoyer 1 si ladateapparaît plus d'une fois dans la liste. Tu peux utiliser la méthodecountpour compter le nombre de fois qu'un élément apparaît dans une liste.Rappel : la méthode
counts'utilise sur une liste en lui passant en argument la valeur à compter :>>> [1,3,1,5].count(1) 2Solution
Pour chaque
datede 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
doublonsplusieurs fois dans la console. Quelle semble être la probabilité d'avoir des doubles ?Solution
On appelle la fonction
doublonsdans 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
doublonsL'idée est la suivante : créer une liste en compréhension qui appelle la fonction
doublons1000 fois. Chacun des éléments de cette liste est donc 0 ou 1 et on obtient facilement la moyenne en s'aidant de la fonctionsumAjoute dans l'éditeur une variable
pen dehors de la fonctiondoublonsqui calcule la probabilité avec la méthode précédente. Puis affiche cette probabilité à l'aide d'unprintSolution
Pour calculer la valeur de la variable
pil nous faut tout d'abord une liste de 1000 éléments qui correspondent aux résultats de la fonctiondoublonsOn 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
pqu'on affiche ensuite à l'aide d'unprintfrom 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
doublonspour qu'elle prenne un argument correspondant à la taille du groupe. Modifie en conséquence le calcul deppour que la probabilité obtenue corresponde au cas du groupe de 30 personnes.Solution
Il faut modifier l'en tête de la fonction
doublonsque l'on fait dépendre d'un argumentn, ainsi que la variableanniversairesqui doit contenirndates.On adapte ensuite le calcul de
ppour appeler la fonctiondoublonsavec 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
Xqui correspond aux différentes tailles de groupes et une liste d'ordonnéesYqui 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
pen 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
Xde 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 listeYqui calcule la probabilitépd'avoir des anniversaires le même jour pour chacune de ces tailles de groupe.Solution
Pour définir
Xle plus simple est de convertir en liste une séquence renvoyée parrangeà l'aide de la fonctionlistOn définit
Yen compréhension en calculant la probabilitéppour 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
pyplotde la librairie matplotlib. J'ai déjà importépyplotsous l'aliaspltUtilise les fonctions
plotetshowdu modulepyplotpour 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 fonctionplotLa fonction
shownous 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.