TP9 - Retour sur les listes ¶
# on importe les bibliothèques utiles
import numpy as np
import random
import matplotlib.pyplot as plt
Statistiques du jeu des 30 points¶
Voici une "variante" de la fonction jeu30points() du TP8.
Au lieu d'afficher les deux dés et le nouveau score, elle retourne la liste des scores obtenus jusqu'à la victoire.
def score_lancer(de1, de2):
res = 0
if de1 == de2 :
if de1 in [1, 2, 4, 5] :
res = 5
if de1 == 6 :
res = 25
return(res)
def jeu30points() :
score = 0
lst_scores = []
while score < 30 :
res1 = random.randint(1,6)
res2 = random.randint(1,6)
if (res1 == 3 and res2 == 3) :
score = 0
score = score + score_lancer(res1,res2)
lst_scores.append(score)
return(lst_scores)
# test de lancer2des()
jeu30points()
La longueur de cette liste fournit le nombre de coups à jouer jusqu'à la victoire.
Regardons comment ce nombre varie sur 5000 parties...
n = 5000
y = []
for i in range(n):
nb = len(jeu30points())
y.append(nb)
nbCl = int(n**(1/3))
plt.hist(y, bins=nbCl, density=True, edgecolor='black')
plt.axvline(x=sum(y)/n, color='red', label='Moyenne')
plt.legend(loc='best')
plt.show()
Cette représentation graphique révèle une variation asymétrique autour de la moyenne.
Regardons d'une autre manière cette variation autour de la moyenne calculée cette fois sur 50 parties...
n = 50
x = np.arange(n)
y = []
for i in range(n):
nb = len(jeu30points())
y.append(nb)
moy = [sum(y)/n for i in x]
plt.plot(x, y)
plt.plot(x, moy, 'r', label='Moyenne')
plt.legend(loc='best')
plt.show()
print("Moyenne :",moy[0])
Exécuter plusieurs fois le programme précédent. Que remarquez-vous ?
La moyenne change à chaque fois, mais comment varie-t-elle ?
Demandons à la machine d'exécuter 5000 fois ce programme et de représenter graphiquement la distribution de ces 5000 moyennes calculées...
n = 50
N = 5000
moy = []
for j in range(N):
y = []
for i in range(n):
nb = len(jeu30points())
y.append(nb)
moy.append(sum(y)/n)
nbCl = int(N**(1/3))
plt.hist(moy, bins=nbCl, density=True, edgecolor='black')
plt.axvline(x=sum(moy)/N, color='red', label='Moyenne des moyennes')
plt.legend(loc='best')
plt.show()
Cette forme "en cloche" est typique d'une distribution connue sous le nom de "loi normale" ou "loi gaussienne".
Ce qui est remarquable, c'est que le hasard est "contrôlé" au niveau de la moyenne, autrement dit il est tout à fait possible de prévoir le comportement de la moyenne pour un phénomène pourtant bien aléatoire au départ.
Il s'agit d'une propriété mathématique appelée Théorème Central Limite qui est en fait à l'origine de tous les modèles de prévisions utilisés en finance, en assurance, en banque, en météorologie, en biologie...
En modifiant maintenant la fonction jeu30pointsVSmachine() du TP8, nous obtenons cette "variante" qui retourne 1 si le joueur gagne et 0 sinon.
def jeu30pointsVSmachine() :
score = 0
score_ordi = 0
while score < 30 and score_ordi < 30 :
res1 = random.randint(1,6)
res2 = random.randint(1,6)
if (res1 == 3 and res2 == 3) :
score = 0
score = score + score_lancer(res1,res2)
res1_ordi = random.randint(1,6)
res2_ordi = random.randint(1,6)
if (res1_ordi == 3 and res2_ordi == 3) :
score_ordi = 0
score_ordi = score_ordi + score_lancer(res1_ordi,res2_ordi)
if score >= 30 :
res = 1
else :
res = 0
return(res)
# test de jeu30pointsVSmachine()
jeu30pointsVSmachine()
Le nombre de victoires du joueur sur 100 parties correspond au pourcentage de victoires du joueur.
Demandons à la machine de simuler 2000 séries de 100 parties, et représentons graphiquement la distribution de ces 2000 pourcentages...
n = 100
N = 2000
y = []
for i in range(N) :
nb_victoires_joueur = 0
for i in range(n) :
nb_victoires_joueur = nb_victoires_joueur + jeu30pointsVSmachine()
y.append(nb_victoires_joueur)
nbCl = int(N**(1/3))
plt.hist(y, bins=nbCl, density=True, edgecolor='black')
plt.axvline(x=sum(y)/N, color='red', label='Pourcentage moyen\nde victoires du joueur')
plt.legend(loc='best')
plt.show()
Le jeu semble plutôt bien équilibré, mais peut-on le truqer ?
La fonction random.randint(1,6) permet de simuler le lancer d'un dé équilibré.
La fonction random.choices([1, 2, 3, 4, 5, 6],[1/6, 1/6, 1/6, 1/6, 1/6, 1/6])[0] est équivalente, mais elle précise la chance d'obtenir chaque entier entre 1 et 6.
Le fait d'avoir toujours 1/6 signifie que le dé est ici bien équilibré.
Modifier la fonction jeu30pointsVSmachine() de manière à avantager le joueur.
Représenter graphiquement l'avantage donné au joueur.
# modification de jeu30pointsVSmachine()
# test jeu30pointsVSmachine()
jeu30pointsVSmachine()
# représentation graphique de l'avantage donné au joueur
n = 100
N = 2000
y = []
for i in range(N) :
nb_victoires_joueur = 0
for i in range(n) :
nb_victoires_joueur = nb_victoires_joueur + jeu30pointsVSmachine()
y.append(nb_victoires_joueur)
nbCl = int(N**(1/3))
plt.hist(y, bins=nbCl, density=True, edgecolor='black')
plt.axvline(x=sum(y)/N, color='red', label='Pourcentage moyen\nde victoires du joueur')
plt.legend(loc='best')
plt.show()
Statistiques du jeu du premier pile¶
En suivant la même démarche, étudier les statistiques du jeu du premier pile.
# définition de jeu1erPile() qui retourne le nombre de lancers jusqu'à l'obtention du premier pile.
# on pourra modéliser le lancer d'une pièce par le choix d'un entier entre 0 (face) et 1 (pile)
# test de jeu1erPile()
jeu1erPile()
# distribution du nombre de lancers jusqu'au premier pile (5000 réalisations)
# variation du nombre de lancers jusqu'au premier pile autour de la moyenne (50 réalisations)
# distribution des 5000 moyennes (calculées à partir de 50 réalisations)
# définition de jeu1erPileVSmachine() qui retourne 1 si le joueur gagne et 0 sinon
# test de jeu1erPileVSmachine()
jeu1erPileVSmachine()
# distribution des 2000 pourcentages de victoires du joueurs (calculés à partir de 100 réalisations)
n = 100
N = 2000
y = []
for i in range(N) :
nb_victoires_joueur = 0
for i in range(n) :
res = jeu1erPileVSmachine()
while res == -1 :
res = jeu1erPileVSmachine()
nb_victoires_joueur = nb_victoires_joueur + res
y.append(nb_victoires_joueur)
nbCl = int(N**(1/3))
plt.hist(y, bins=nbCl, density=True, edgecolor='black')
plt.axvline(x=sum(y)/N, color='red', label='Pourcentage moyen\nde victoires du joueur')
plt.legend(loc='best')
plt.show()
Ce dernier graphique vous paraît-il cohérent ?