→ Lien vers les résultats obtenus.
Dépendances :
import numpy as np
import numpy.random as rn
rn.seed(0) # Pour obtenir les mêmes résultats
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context="notebook", style="darkgrid", palette="hls", font="sans-serif", font_scale=1.4)
Première fonction : pour tirer trois dés, à 6 faces, indépendants.
def tirage(nb=1):
""" Renvoie un numpy array de taille (3,) si nb == 1, sinon (nb, 3)."""
if nb == 1:
return rn.randint(1, 7, 3)
else:
return rn.randint(1, 7, (nb, 3))
Testons là :
tirage()
array([5, 6, 1])
tirage(10)
array([[4, 4, 4], [2, 4, 6], [3, 5, 1], [1, 5, 3], [2, 1, 2], [6, 2, 6], [1, 2, 5], [4, 1, 4], [6, 1, 3], [4, 1, 2]])
Le jeu de 151 associe les points suivants, multiples de 50, aux tirages de 3 dés :
COMPTE_SUITE = False # Savoir si on implémente aussi la variante avec les suites
def _points(valeurs, compte_suite=COMPTE_SUITE):
if valeurs[0] == valeurs[1] == valeurs[2]: # Un brelan !
if valeurs[0] == 1:
return 700
else:
return 100 * valeurs[0]
else: # Pas de brelan
# Code pour compter les suites :
bonus_suite = compte_suite and set(np.diff(np.sort(valeurs))) == {1}
return 100 * (np.sum(valeurs == 1) + bonus_suite) + 50 * np.sum(valeurs == 5)
def points(valeurs, compte_suite=COMPTE_SUITE):
""" Calcule les points du tirage correspondant à valeurs.
- si valeurs est de taille (3,), renvoie un seul entier,
- si valeurs est de taille (nb, 3), renvoie un tableau de points.
"""
if len(np.shape(valeurs)) > 1:
return np.array([_points(valeurs[i,:], compte_suite) for i in range(np.shape(valeurs)[0])])
else:
return _points(valeurs, compte_suite)
Testons ces fonctions :
valeurs = tirage()
print("La valeur {} donne {:>5} points.".format(valeurs, points(valeurs)))
La valeur [4 6 4] donne 0 points.
for _ in range(20):
valeurs = tirage()
print("- La valeur {} donne {:>5} points.".format(valeurs, points(valeurs)))
- La valeur [4 1 2] donne 100 points. - La valeur [2 2 1] donne 100 points. - La valeur [3 5 4] donne 50 points. - La valeur [4 3 5] donne 50 points. - La valeur [3 1 1] donne 200 points. - La valeur [5 6 6] donne 50 points. - La valeur [1 5 2] donne 150 points. - La valeur [5 2 3] donne 50 points. - La valeur [3 1 2] donne 100 points. - La valeur [2 2 2] donne 200 points. - La valeur [4 4 3] donne 0 points. - La valeur [4 1 4] donne 100 points. - La valeur [6 5 2] donne 50 points. - La valeur [3 5 4] donne 50 points. - La valeur [5 5 5] donne 500 points. - La valeur [4 5 5] donne 100 points. - La valeur [5 1 5] donne 200 points. - La valeur [4 3 6] donne 0 points. - La valeur [6 6 1] donne 100 points. - La valeur [2 6 2] donne 0 points.
Testons quelques valeurs particulières :
for valeur in range(1, 7):
valeurs = valeur * np.ones(3, dtype=int)
print("- La valeur {} donne {:>5} points.".format(valeurs, points(valeurs)))
- La valeur [1 1 1] donne 700 points. - La valeur [2 2 2] donne 200 points. - La valeur [3 3 3] donne 300 points. - La valeur [4 4 4] donne 400 points. - La valeur [5 5 5] donne 500 points. - La valeur [6 6 6] donne 600 points.
for valeurs in [np.array([2, 3, 6]), np.array([1, 3, 6]), np.array([1, 1, 6])]:
print("- La valeur {} donne {:>5} points.".format(valeurs, points(valeurs)))
- La valeur [2 3 6] donne 0 points. - La valeur [1 3 6] donne 100 points. - La valeur [1 1 6] donne 200 points.
for valeurs in [np.array([2, 3, 6]), np.array([5, 3, 6]), np.array([5, 5, 6])]:
print("- La valeur {} donne {:>5} points.".format(valeurs, points(valeurs)))
- La valeur [2 3 6] donne 0 points. - La valeur [5 3 6] donne 50 points. - La valeur [5 5 6] donne 100 points.
→ C'est bon, tout marche !
Note : certaines variants du 151 accordent une valeur supplémentaire aux suites (non ordonnées) : [1, 2, 3] vaut 200, [2, 3, 4] vaut 100, et [3, 4, 5] et [4, 5, 6] vaut 150.
Ce n'est pas difficile à intégrer dans notre fonction points
.
for valeurs in [np.array([1, 2, 3]), np.array([2, 3, 4]), np.array([3, 4, 5]), np.array([4, 5, 6])]:
print("- La valeur {} donne {:>5} points.".format(valeurs, points(valeurs)))
- La valeur [1 2 3] donne 100 points. - La valeur [2 3 4] donne 0 points. - La valeur [3 4 5] donne 50 points. - La valeur [4 5 6] donne 50 points.
Testons ces fonctions :
valeurs = tirage(10)
print(valeurs)
print(points(valeurs))
[[4 1 6] [1 2 3] [5 3 1] [6 4 3] [3 6 1] [6 2 1] [3 3 4] [3 4 3] [2 3 4] [4 4 3]] [100 100 150 0 100 100 0 0 0 0]
On peut faire quelques tests statistiques dès maintenant :
def moyenneTirage(nb=1000):
return np.mean(points(tirage(nb), False))
def moyenneTirage_avecSuite(nb=1000):
return np.mean(points(tirage(nb), True))
for p in range(2, 7):
nb = 10 ** p
print("- Pour {:>7} tirages, les tirages valent en moyenne {:>4} points.".format(nb, moyenneTirage(nb)))
print("- Pour {:>7} tirages, les tirages valent en moyenne {:>4} points si on compte aussi les suites.".format(nb, moyenneTirage_avecSuite(nb)))
- Pour 100 tirages, les tirages valent en moyenne 95.0 points. - Pour 100 tirages, les tirages valent en moyenne 100.0 points si on compte aussi les suites. - Pour 1000 tirages, les tirages valent en moyenne 81.2 points. - Pour 1000 tirages, les tirages valent en moyenne 98.0 points si on compte aussi les suites. - Pour 10000 tirages, les tirages valent en moyenne 85.05 points. - Pour 10000 tirages, les tirages valent en moyenne 97.3 points si on compte aussi les suites. - Pour 100000 tirages, les tirages valent en moyenne 85.817 points. - Pour 100000 tirages, les tirages valent en moyenne 96.6435 points si on compte aussi les suites. - Pour 1000000 tirages, les tirages valent en moyenne 85.32135 points. - Pour 1000000 tirages, les tirages valent en moyenne 96.55695 points si on compte aussi les suites.
Ça semble converger vers 85 : en moyenne, un tirage vaut entre 50 et 100 points, plutôt du côté des 100. Et si on compte les suites, la valeur moyenne d'un tirage vaut plutôt 96 points (ça augmente comme prévu, mais ça augmente peu).
def moyenneStdTirage(nb=1000):
pts = points(tirage(nb))
return np.mean(pts), np.std(pts)
for p in range(2, 7):
nb = 10 ** p
m, s = moyenneStdTirage(nb)
print("- Pour {:>7} tirages, les tirages valent en moyenne {:6.2f} +- {:>6.2f} points.".format(nb, m, s))
- Pour 100 tirages, les tirages valent en moyenne 79.00 +- 83.12 points. - Pour 1000 tirages, les tirages valent en moyenne 88.15 +- 92.42 points. - Pour 10000 tirages, les tirages valent en moyenne 86.97 +- 95.47 points. - Pour 100000 tirages, les tirages valent en moyenne 85.26 +- 92.53 points. - Pour 1000000 tirages, les tirages valent en moyenne 85.31 +- 92.73 points.
def plotPoints(nb=2000):
pts = np.sort(points(tirage(nb)))
m = np.mean(pts)
plt.figure()
plt.plot(pts, 'ro')
plt.title("Valeurs de {} tirages. Moyenne = {:.2f}".format(nb, m))
plt.show()
plotPoints()
plotPoints(10**5)
plotPoints(10**6)
def probaPoints(nb=1000, pt=0, compte_suite=COMPTE_SUITE):
pts = points(tirage(nb), compte_suite)
return np.sum(pts == pt) / float(nb)
for p in range(2, 7):
nb = 10 ** p
prob = probaPoints(nb, compte_suite=False)
print("- Pour {:>7} tirages, il y a une probabilité {:7.2%} d'avoir 0 point.".format(nb, prob))
prob = probaPoints(nb, compte_suite=True)
print("- Pour {:>7} tirages, il y a une probabilité {:7.2%} d'avoir 0 point si on compte les suites.".format(nb, prob))
- Pour 100 tirages, il y a une probabilité 16.00% d'avoir 0 point. - Pour 100 tirages, il y a une probabilité 28.00% d'avoir 0 point si on compte les suites. - Pour 1000 tirages, il y a une probabilité 27.00% d'avoir 0 point. - Pour 1000 tirages, il y a une probabilité 26.70% d'avoir 0 point si on compte les suites. - Pour 10000 tirages, il y a une probabilité 27.73% d'avoir 0 point. - Pour 10000 tirages, il y a une probabilité 24.11% d'avoir 0 point si on compte les suites. - Pour 100000 tirages, il y a une probabilité 27.90% d'avoir 0 point. - Pour 100000 tirages, il y a une probabilité 24.97% d'avoir 0 point si on compte les suites. - Pour 1000000 tirages, il y a une probabilité 27.81% d'avoir 0 point. - Pour 1000000 tirages, il y a une probabilité 25.00% d'avoir 0 point si on compte les suites.
Donc un tirage apporte 85 points en moyenne, mais il y a environ 28% de chance qu'un tirage rate.
Si on compte les suites, un tirage apporte 97 points en moyenne, mais il y a environ 25% de chance qu'un tirage rate.
# valeursPossibles = list(set(points(tirage(10000))))
valeursPossibles = [0, 50, 100, 150, 200, 250, 300, 400, 500, 600, 700]
for p in range(4, 7):
nb = 10 ** p
tirages = tirage(nb)
pts = points(tirages, False)
pts_s = points(tirages, True)
print("\n- Pour {:>7} tirages :".format(nb))
for pt in valeursPossibles:
prob = np.sum(pts == pt) / float(nb)
print(" - Il y a une probabilité {:7.2%} d'avoir {:3} point{}.".format(prob, pt, 's' if pt > 0 else ''))
prob = np.sum(pts_s == pt) / float(nb)
print(" - Il y a une probabilité {:7.2%} d'avoir {:3} point{} si on compte les suites.".format(prob, pt, 's' if pt > 0 else ''))
- Pour 10000 tirages : - Il y a une probabilité 28.33% d'avoir 0 point. - Il y a une probabilité 25.58% d'avoir 0 point si on compte les suites. - Il y a une probabilité 22.47% d'avoir 50 points. - Il y a une probabilité 16.68% d'avoir 50 points si on compte les suites. - Il y a une probabilité 27.77% d'avoir 100 points. - Il y a une probabilité 27.98% d'avoir 100 points si on compte les suites. - Il y a une probabilité 10.70% d'avoir 150 points. - Il y a une probabilité 16.49% d'avoir 150 points si on compte les suites. - Il y a une probabilité 7.28% d'avoir 200 points. - Il y a une probabilité 9.82% d'avoir 200 points si on compte les suites. - Il y a une probabilité 1.19% d'avoir 250 points. - Il y a une probabilité 1.19% d'avoir 250 points si on compte les suites. - Il y a une probabilité 0.42% d'avoir 300 points. - Il y a une probabilité 0.42% d'avoir 300 points si on compte les suites. - Il y a une probabilité 0.50% d'avoir 400 points. - Il y a une probabilité 0.50% d'avoir 400 points si on compte les suites. - Il y a une probabilité 0.41% d'avoir 500 points. - Il y a une probabilité 0.41% d'avoir 500 points si on compte les suites. - Il y a une probabilité 0.49% d'avoir 600 points. - Il y a une probabilité 0.49% d'avoir 600 points si on compte les suites. - Il y a une probabilité 0.44% d'avoir 700 points. - Il y a une probabilité 0.44% d'avoir 700 points si on compte les suites. - Pour 100000 tirages : - Il y a une probabilité 27.73% d'avoir 0 point. - Il y a une probabilité 24.98% d'avoir 0 point si on compte les suites. - Il y a une probabilité 22.68% d'avoir 50 points. - Il y a une probabilité 16.95% d'avoir 50 points si on compte les suites. - Il y a une probabilité 27.60% d'avoir 100 points. - Il y a une probabilité 27.56% d'avoir 100 points si on compte les suites. - Il y a une probabilité 10.98% d'avoir 150 points. - Il y a une probabilité 16.71% d'avoir 150 points si on compte les suites. - Il y a une probabilité 7.39% d'avoir 200 points. - Il y a une probabilité 10.18% d'avoir 200 points si on compte les suites. - Il y a une probabilité 1.34% d'avoir 250 points. - Il y a une probabilité 1.34% d'avoir 250 points si on compte les suites. - Il y a une probabilité 0.45% d'avoir 300 points. - Il y a une probabilité 0.45% d'avoir 300 points si on compte les suites. - Il y a une probabilité 0.44% d'avoir 400 points. - Il y a une probabilité 0.44% d'avoir 400 points si on compte les suites. - Il y a une probabilité 0.44% d'avoir 500 points. - Il y a une probabilité 0.44% d'avoir 500 points si on compte les suites. - Il y a une probabilité 0.49% d'avoir 600 points. - Il y a une probabilité 0.49% d'avoir 600 points si on compte les suites. - Il y a une probabilité 0.46% d'avoir 700 points. - Il y a une probabilité 0.46% d'avoir 700 points si on compte les suites. - Pour 1000000 tirages : - Il y a une probabilité 27.87% d'avoir 0 point. - Il y a une probabilité 25.08% d'avoir 0 point si on compte les suites. - Il y a une probabilité 22.25% d'avoir 50 points. - Il y a une probabilité 16.66% d'avoir 50 points si on compte les suites. - Il y a une probabilité 27.70% d'avoir 100 points. - Il y a une probabilité 27.72% d'avoir 100 points si on compte les suites. - Il y a une probabilité 11.13% d'avoir 150 points. - Il y a une probabilité 16.72% d'avoir 150 points si on compte les suites. - Il y a une probabilité 7.37% d'avoir 200 points. - Il y a une probabilité 10.14% d'avoir 200 points si on compte les suites. - Il y a une probabilité 1.37% d'avoir 250 points. - Il y a une probabilité 1.37% d'avoir 250 points si on compte les suites. - Il y a une probabilité 0.46% d'avoir 300 points. - Il y a une probabilité 0.46% d'avoir 300 points si on compte les suites. - Il y a une probabilité 0.47% d'avoir 400 points. - Il y a une probabilité 0.47% d'avoir 400 points si on compte les suites. - Il y a une probabilité 0.46% d'avoir 500 points. - Il y a une probabilité 0.46% d'avoir 500 points si on compte les suites. - Il y a une probabilité 0.46% d'avoir 600 points. - Il y a une probabilité 0.46% d'avoir 600 points si on compte les suites. - Il y a une probabilité 0.46% d'avoir 700 points. - Il y a une probabilité 0.46% d'avoir 700 points si on compte les suites.
On devrait faire des histogrammes, mais j'ai la flemme...
Ces quelques expériences montrent qu'on a :
Autant de chance d'avoir 100 points que 0 ? Et oui !
La variante comptant les suites augmente la chance d'avoir 200 points (de 7.5% à 10%), d'avoir 150 points (de 11% à 16%), et diminue la chance d'avoir 0 point, mais ne change pas vraiment le reste du jeu.
DEBUG = False # Par défaut, on n'affiche rien
def unJeu(joueur, compte, total, debug=DEBUG):
accu = 0
if debug: print(" - Le joueur {.__name__} commence à jouer, son compte est {} et le total est {} ...".format(joueur, compte, total))
t = tirage()
nbLance = 1
if points(t) == 0:
if debug: print(" - Hoho, ce tirage {} vallait 0 points, le joueur doit arrêter.".format(t))
return 0, nbLance
if debug: print(" - Le joueur a obtenu {} ...".format(t))
while compte + accu <= total and joueur(compte, accu, t, total):
accu += points(t)
t = tirage()
nbLance += 1
if debug: print(" - Le joueur a décidé de rejouer, accumulant {} points, et a ré-obtenu {} ...".format(accu, t))
if points(t) == 0:
if debug: print(" - Hoho, ce tirage {} vallait 0 points, le joueur doit arrêter.".format(t))
break
accu += points(t)
if compte + accu > total:
if debug: print(" - Le joueur a dépassé le total : impossible de marquer ! compte = {} + accu = {} > total = {} !".format(compte, accu, total))
return 0, nbLance
else:
if accu > 0:
if debug: print(" - Le joueur peut marquer les {} points accumulés en {} lancés !".format(accu, nbLance))
return accu, nbLance
def unePartie(joueurs, total=1000, debug=DEBUG, i0=0):
assert len(joueurs) == 2, "Erreur, seulement 2 joueurs sont acceptés !"
comptes = [0, 0]
nbCoups = [0, 0]
nbLances = [0, 0]
scores = [[0], [0]]
if debug: print("- Le joueur #{} va commencer ...".format(i0))
i = i0
while max(comptes) != total: # Tant qu'aucun joueur n'a gagné
nbCoups[i] += 1
if debug: print("- C'est au joueur #{} ({.__name__}) de jouer, son compte est {} et le total est {} ...".format(i, joueurs[i], comptes[i], total))
accu, nbLance = unJeu(joueurs[i], comptes[i], total, debug)
nbLances[i] += nbLance
if accu > 0:
comptes[i] += accu
scores[i].append(comptes[i]) # Historique
if comptes[i] == total:
if debug: print("- Le joueur #{} ({.__name__}) a gagné en {} coups et {} lancés de dés !".format(i, joueurs[i], nbCoups[i], nbLances[i]))
if debug: print("- Le joueur #{} ({.__name__}) a perdu, avec un score de {}, après {} coups et {} lancés de dés !".format(i^1, joueurs[i^1], comptes[i^1], nbCoups[i^1], nbLances[i^1]))
return i, scores
i ^= 1 # 0 → 1, 1 → 0 (ou exclusif)
# Note : on pourrait implémenter une partie à plus de 2 joueurs
On doit définir des stratégies, sous la forme de fonctions joueur(compte, accu, t, total)
, qui renvoie True
si elle doit continuer à jouer, ou False
si elle doit marquer.
D'abord, deux stratégies un peu stupides :
def unCoup(compte, accu, t, total):
""" Stratégie qui marque toujours au premier coup, peu importe le 1er tirage obtenu."""
return False # Marque toujours !
def jusquauBout(compte, accu, t, total):
""" Stratégie qui ne marque que si elle peut gagner exactement ."""
if compte + accu + points(t) >= total:
return False # Marque si elle peut gagner
else:
return True # Continue à jouer
Une autre stratégie, qui marche seulement si elle peut marquer plus de X points (100, 150 etc).
C'est la version plus "gourmande" de unCoup
, qui marque si elle a plus de 50 points.
def auMoinsX(X):
def joueur(compte, accu, t, total):
""" Stratégie qui marque si elle a eu plus de {} points.""".format(X)
if accu + points(t) >= X:
return False # Marque si elle a obtenu plus de X points
elif compte + accu + points(t) == total:
return False # Marque si elle peut gagner
elif total - compte < X:
# S'il reste peu de points, marque toujours
# (sinon la stratégie d'accumuler plus de X points ne marche plus)
return False
else:
return True # Continue de jouer, essaie d'obtenir X points
joueur.__name__ = "auMoins{}".format(X) # Triche sur le nom
return joueur
auMoins50 = auMoinsX(50) # == unCoup, en fait
auMoins100 = auMoinsX(100)
auMoins150 = auMoinsX(150)
auMoins200 = auMoinsX(200) # Commence à devenir très audacieux
auMoins250 = auMoinsX(250)
auMoins300 = auMoinsX(300) # Compètement fou, très peu de chance de marquer ça ou plus!
auMoins350 = auMoinsX(350)
auMoins400 = auMoinsX(400)
auMoins450 = auMoinsX(450)
auMoins500 = auMoinsX(500)
auMoins550 = auMoinsX(550)
auMoins600 = auMoinsX(600)
auMoins650 = auMoinsX(650)
auMoins700 = auMoinsX(700)
# On pourrait continuer ...
auMoins800 = auMoinsX(800)
auMoins850 = auMoinsX(850)
auMoins900 = auMoinsX(900)
auMoins950 = auMoinsX(950)
auMoins1000 = auMoinsX(1000)
Une autre stratégie "stupide" : décider aléatoirement, selon une loi de Bernoulli, si elle continue ou si elle s'arrête.
def bernoulli(p=0.5):
def joueur(compte, accu, t, total):
""" Marque les points accumulés avec probabilité p = {} (Bernoulli).""".format(p)
return rn.random() > p
joueur.__name__ = "bernoulli_{:.3g}".format(p)
return joueur
joueurs = [unCoup, unCoup]
total = 200
unePartie(joueurs, total, True)
unePartie(joueurs, total)
- Le joueur #0 va commencer ... - C'est au joueur #0 (unCoup) de jouer, son compte est 0 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 0 et le total est 200 ... - Le joueur a obtenu [4 5 2] ... - Le joueur peut marquer les 50 points accumulés en 1 lancés ! - C'est au joueur #1 (unCoup) de jouer, son compte est 0 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 0 et le total est 200 ... - Hoho, ce tirage [3 4 2] vallait 0 points, le joueur doit arrêter. - C'est au joueur #0 (unCoup) de jouer, son compte est 50 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 50 et le total est 200 ... - Le joueur a obtenu [3 2 5] ... - Le joueur peut marquer les 50 points accumulés en 1 lancés ! - C'est au joueur #1 (unCoup) de jouer, son compte est 0 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 0 et le total est 200 ... - Le joueur a obtenu [3 4 1] ... - Le joueur peut marquer les 100 points accumulés en 1 lancés ! - C'est au joueur #0 (unCoup) de jouer, son compte est 100 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 100 et le total est 200 ... - Hoho, ce tirage [4 3 4] vallait 0 points, le joueur doit arrêter. - C'est au joueur #1 (unCoup) de jouer, son compte est 100 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 100 et le total est 200 ... - Le joueur a obtenu [1 1 1] ... - Le joueur a dépassé le total : impossible de marquer ! compte = 100 + accu = 700 > total = 200 ! - C'est au joueur #0 (unCoup) de jouer, son compte est 100 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 100 et le total est 200 ... - Hoho, ce tirage [4 3 4] vallait 0 points, le joueur doit arrêter. - C'est au joueur #1 (unCoup) de jouer, son compte est 100 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 100 et le total est 200 ... - Le joueur a obtenu [1 5 1] ... - Le joueur a dépassé le total : impossible de marquer ! compte = 100 + accu = 250 > total = 200 ! - C'est au joueur #0 (unCoup) de jouer, son compte est 100 et le total est 200 ... - Le joueur unCoup commence à jouer, son compte est 100 et le total est 200 ... - Le joueur a obtenu [6 1 6] ... - Le joueur peut marquer les 100 points accumulés en 1 lancés ! - Le joueur #0 (unCoup) a gagné en 5 coups et 5 lancés de dés ! - Le joueur #1 (unCoup) a perdu, avec un score de 100, après 4 coups et 4 lancés de dés !
(0, [[0, 200], [0, 100]])
joueurs = [unCoup, jusquauBout]
total = 200
unePartie(joueurs, total)
(1, [[0, 50], [0, 100, 200]])
joueurs = [unCoup, auMoins100]
total = 500
unePartie(joueurs, total)
(1, [[0, 100, 200, 350, 400], [0, 100, 200, 350, 450, 500]])
joueurs = [unCoup, auMoins200]
total = 1000
unePartie(joueurs, total)
(0, [[0, 100, 150, 250, 400, 600, 700, 750, 900, 1000], [0, 200, 300, 550, 750, 900, 950]])
On peut maintenant lancer plusieurs centaines de simulations de parties, sans afficher le déroulement de chaque parties.
La fonction unePartie
renvoie un tuple, (i, comptes)
, où :
i
est l'indice (0 ou 1) du joueur ayant gagné la partie,comptes
est une liste contenant les deux historiques des points des deux joueurs.Par exemple, pour un total = 500
, la sortie (1, [[0, 100, 150, 250, 450], [0, 50, 450, 500]])
signifie :
def desParties(nb, joueurs, total=1000, i0=0):
indices, historiques = [], []
for _ in range(nb):
i, h = unePartie(joueurs, total=total, i0=i0, debug=False)
indices.append(i)
historiques.append(h)
return indices, historiques
Par exemple, on peut opposer le joueur pas courageux (unCoup
) au joueur très gourmand (jusquauBout
) sur 100 parties avec un total de 250 points :
def freqGain(indiceMoyen, i):
# (1^i) + ((-1)**(i==0)) * indiceMoyen
if i == 0:
return 1 - indiceMoyen
else:
return indiceMoyen
def afficheResultatsDesParties(nb, joueurs, total, indices, historiques):
indiceMoyen = np.mean(indices)
pointsFinaux = [np.mean(list(historiques[k][i][-1] for k in range(nb))) for i in [0, 1]]
print("Dans {} parties simulées, contre le total {} :".format(nb, total))
for i in [0, 1]:
print(" - le joueur {} ({.__name__:<11}) a gagné {:>5.2%} du temps, et a eu un score final moyen de {:>5g} points ...".format(i, joueurs[i], freqGain(indiceMoyen, i), pointsFinaux[i]))
nb = 10000
joueurs = [unCoup, jusquauBout]
total = 1000
indices, historiques = desParties(nb, joueurs, total)
afficheResultatsDesParties(nb, joueurs, total, indices, historiques)
Dans 10000 parties simulées, contre le total 1000 : - le joueur 0 (unCoup ) a gagné 12.11% du temps, et a eu un score final moyen de 553.635 points ... - le joueur 1 (jusquauBout) a gagné 87.89% du temps, et a eu un score final moyen de 977.425 points ...
nb = 10000
joueurs = [unCoup, jusquauBout]
total = 500
indices, historiques = desParties(nb, joueurs, total)
afficheResultatsDesParties(nb, joueurs, total, indices, historiques)
Dans 10000 parties simulées, contre le total 500 : - le joueur 0 (unCoup ) a gagné 24.83% du temps, et a eu un score final moyen de 315.35 points ... - le joueur 1 (jusquauBout) a gagné 75.17% du temps, et a eu un score final moyen de 453.565 points ...
nb = 10000
joueurs = [unCoup, jusquauBout]
total = 5000
indices, historiques = desParties(nb, joueurs, total)
afficheResultatsDesParties(nb, joueurs, total, indices, historiques)
Dans 10000 parties simulées, contre le total 5000 : - le joueur 0 (unCoup ) a gagné 0.04% du temps, et a eu un score final moyen de 1751.06 points ... - le joueur 1 (jusquauBout) a gagné 99.96% du temps, et a eu un score final moyen de 4999.95 points ...
Affichons une première courbe qui montrera la supériorité d'une stratégie face à la plus peureuse, en fonction du total.
def plotResultatsDesParties(nb, joueurs, totaux):
N = len(totaux)
indicesMoyens = []
for total in totaux:
indices, _ = desParties(nb, joueurs, total)
indicesMoyens.append(np.mean(indices))
plt.figure()
plt.plot(totaux, indicesMoyens, 'ro')
plt.xlabel("Objectif (points totaux à atteindre)")
plt.ylabel("Taux de victoire de 1 face à 0")
plt.title("Taux de victoire du joueur 1 ({.__name__}) face au joueur 0 ({.__name__}),\n pour {} parties simulees pour chaque total.".format(joueurs[1], joueurs[0], nb))
plt.show()
nb = 1000
joueurs = [unCoup, jusquauBout]
totaux = [50, 100, 150, 200, 250, 300, 350, 400, 450, 500]
plotResultatsDesParties(nb, joueurs, totaux)
nb = 1000
joueurs = [unCoup, jusquauBout]
totalMax = 2000
totaux = list(range(50, totalMax + 50, 50))
plotResultatsDesParties(nb, joueurs, totaux)
D'autres comparaisons, entre stratégies gourmandes.
nb = 5000
joueurs = [auMoins100, auMoins200]
totalMax = 1000
totaux = list(range(50, totalMax + 50, 50))
plotResultatsDesParties(nb, joueurs, totaux)
nb = 1000
joueurs = [auMoins100, jusquauBout]
totalMax = 2000
totaux = list(range(50, totalMax + 50, 100))
plotResultatsDesParties(nb, joueurs, totaux)
nb = 1000
totalMax = 2000
totaux = list(range(50, totalMax + 50, 50))
joueurs = [unCoup, bernoulli(0.5)]
plotResultatsDesParties(nb, joueurs, totaux)
joueurs = [unCoup, bernoulli(0.1)]
plotResultatsDesParties(nb, joueurs, totaux)
joueurs = [unCoup, bernoulli(0.25)]
plotResultatsDesParties(nb, joueurs, totaux)
joueurs = [unCoup, bernoulli(0.75)]
plotResultatsDesParties(nb, joueurs, totaux)
joueurs = [unCoup, bernoulli(0.9)]
plotResultatsDesParties(nb, joueurs, totaux)
Plutôt que de faire jouer une stratégie face à une autre, et d'utiliser le taux de victoire comme une mesure de performance (ce que j'ai fait plus haut), on peut chercher à mesure un autre taux de victoire.
On peut laisser une stratégie jouer tout seule, et mesurer plutôt le nombre de coup requis pour gagner.
def unePartieSeul(joueur, total=1000, debug=DEBUG):
compte = 0
nbCoups = 0
nbLances = 0
score = [0]
if debug: print("Simulation pour le joueur ({.__name__}), le total à atteindre est {} :".format(joueur, total))
while compte < total: # Tant que joueur n'a pas gagné
nbCoups += 1
if debug: print(" - Coup #{}, son compte est {} / {} ...".format(nbCoups, compte, total))
accu, nbLance = unJeu(joueur, compte, total, debug)
nbLances += nbLance
if accu > 0:
compte += accu
score.append(compte) # Historique
if compte == total:
if debug: print("- Le joueur ({.__name__}) a gagné en {} coups et {} lancés de dés !".format(joueur, nbCoups, nbLances))
return score
Testons ça avec la stratégie naïve unCoup
:
h = unePartieSeul(unCoup, 1000)
print("Partie gagnée en {} coups par le joueur ({.__name__}), avec le score {} ...".format(len(h), unCoup, h))
Partie gagnée en 12 coups par le joueur (unCoup), avec le score [0, 200, 300, 350, 500, 550, 650, 700, 800, 850, 950, 1000] ...
Comme précédemment, on peut générer plusieurs simulations pour la même tâche, et obtenir ainsi une liste d'historiques de jeu.
def desPartiesSeul(nb, joueur, total=1000, debug=False):
historique = []
for _ in range(nb):
h = unePartieSeul(joueur, total=total, debug=debug)
historique.append(h)
return historique
desPartiesSeul(4, unCoup)
[[0, 100, 150, 250, 300, 400, 500, 550, 650, 800, 850, 950, 1000], [0, 100, 200, 300, 350, 400, 550, 650, 750, 800, 900, 950, 1000], [0, 150, 400, 450, 650, 750, 850, 950, 1000], [0, 100, 150, 250, 450, 850, 900, 1000]]
Ce qui nous intéresse est uniquement le nombre de coups qu'une certaine stratégie va devoir jouer avant de gagner :
[len(l)-1 for l in desPartiesSeul(4, unCoup)]
[9, 6, 12, 11]
Avec un joli affichage et un calcul du nombre moyen de coups :
def afficheResultatsDesPartiesSeul(nb, joueur, total, historique):
nbCoupMoyens = np.mean([len(h) - 1 for h in historique])
print("Dans {} parties simulées, contre le total {}, le joueur ({.__name__}) a gagné en moyenne en {} coups ...".format(nb, total, joueur, nbCoupMoyens))
historique = desPartiesSeul(100, unCoup, 1000)
afficheResultatsDesPartiesSeul(100, unCoup, 1000, historique)
Dans 100 parties simulées, contre le total 1000, le joueur (unCoup) a gagné en moyenne en 9.56 coups ...
Comme précédemment, on peut afficher un graphique montrant l'évolution de ce nombre moyen de coups, disons pour $1000$ parties simulées, en fonction du total à atteindre. La courbe obtenue devrait être croissante, mais difficile de prévoir davantage son comportement.
def plotResultatsDesPartiesSeul(nb, joueur, totaux):
N = len(totaux)
nbCoupMoyens = []
for total in totaux:
historique = desPartiesSeul(nb, joueur, total)
nbCoupMoyens.append(np.mean([len(h) - 1 for h in historique]))
plt.figure()
plt.plot(totaux, nbCoupMoyens, 'ro')
plt.xlabel("Objectif (points totaux à atteindre)")
plt.ylabel("Nombre moyen de coups joués avant de gagner")
plt.title("Nombre moyen de coups requis par {.__name__}\n pour {} parties simulées pour chaque total.".format(joueur, nb))
plt.show()
On va utiliser les mêmes paramètres de simulation que précédemment : $1000$ simulations pour chaque total, et des totaux allant de $50$ à $2000$ par pas de $50$.
nb = 1000
totalMax = 2000
totaux = list(range(50, totalMax + 50, 50))
La courbe pour unCoup
permet d'établir le comportement de la stratégie naïve, on pourra ensuite comparer les autres stratégies.
plotResultatsDesPartiesSeul(nb, unCoup, totaux)
Tient, pour
unCoup
, la courbe est linéaire dans le total. C'est assez logique, vue la stratégie utilisée ! On marque à chaque coup, donc le nombre de coups moyens est juste le total divisé par le score moyen. On se rappelle que le score moyen en un tirage est d'environ $96$ points (avec suite), et en effet $2000 / 91 \simeq 21$, ce qu'on lit sur la courbe.
scoreMoyen = 96
total = 2000
total / scoreMoyen
20.833333333333332
Pour jusquauBout
:
plotResultatsDesPartiesSeul(nb, jusquauBout, totaux)
On constate que cette stratégie
jusquauBout
gagne bien plus rapidement que la stratégieunCoup
!
Pour auMoins200
, par exemple :
plotResultatsDesPartiesSeul(nb, auMoins200, totaux)
Pour bernoulli(0.5)
, par exemple :
plotResultatsDesPartiesSeul(nb, bernoulli(0.5), totaux)
Pour bernoulli(0.2)
, par exemple :
plotResultatsDesPartiesSeul(nb, bernoulli(0.2), totaux)
Pour bernoulli(0.8)
, par exemple :
plotResultatsDesPartiesSeul(nb, bernoulli(0.8), totaux)
Ces comparaisons de différentes stratégies de Bernoulli permettent de conclure, comme on le présentait, que la meilleure stratégie (parmi les quelques testées) est la stratégie jusquauBout
!
Toutes les courbes ci dessus montrent un comportement (presque) linéaire du nombre moyen de coups requis pour gagner en fonction du total.
Ainsi, pour comparer différentes stratégies, on peut juste comparer leur nombre de coups moyen pour un certain total, disons $T = 2000$.
def comparerStrategies(joueurs, nb=1000, total=2000):
resultats = []
for joueur in joueurs:
historique = desPartiesSeul(nb, joueur, total)
nbCoupMoyen = np.mean([len(h) - 1 for h in historique])
resultats.append((nbCoupMoyen, joueur.__name__))
# Trier les résultats permet de voir les meilleures stratégies en premier !
return sorted(resultats)
joueurs = [unCoup, jusquauBout]
comparerStrategies(joueurs, nb=nb, total=totalMax)
[(6.2400000000000002, 'jusquauBout'), (17.887, 'unCoup')]
On va comparer toutes les stratégies définies plus haut :
joueurs = [unCoup, jusquauBout]
joueurs += [auMoins50, auMoins100, auMoins150, auMoins200, auMoins250, auMoins300, auMoins350, auMoins400, auMoins450, auMoins500, auMoins550, auMoins600, auMoins650, auMoins700, auMoins800, auMoins850, auMoins900, auMoins950, auMoins1000]
for p in range(0, 20 + 1):
joueurs.append(bernoulli(p/20.))
# print([j.__name__ for j in joueurs])
nb = 1000
totalMax = 2000
resultats = comparerStrategies(joueurs, nb=nb, total=totalMax)
print("Pour le total {} et {} simulations ...".format(totalMax, nb))
for (i, (n, j)) in enumerate(resultats):
print("- La stratégie classée #{:2} / {} est {:<14}, avec un nombre moyen de coups = {:.3g} ...".format(i, len(joueurs), j, n))
Pour le total 2000 et 1000 simulations ... - La stratégie classée # 0 / 42 est jusquauBout, avec un nombre moyen de coups = 6.3 ... - La stratégie classée # 1 / 42 est bernoulli_0, avec un nombre moyen de coups = 7.18 ... - La stratégie classée # 2 / 42 est bernoulli_0.05, avec un nombre moyen de coups = 7.65 ... - La stratégie classée # 3 / 42 est bernoulli_0.1, avec un nombre moyen de coups = 8.16 ... - La stratégie classée # 4 / 42 est auMoins550 , avec un nombre moyen de coups = 8.38 ... - La stratégie classée # 5 / 42 est auMoins500 , avec un nombre moyen de coups = 8.39 ... - La stratégie classée # 6 / 42 est auMoins450 , avec un nombre moyen de coups = 8.43 ... - La stratégie classée # 7 / 42 est auMoins400 , avec un nombre moyen de coups = 8.54 ... - La stratégie classée # 8 / 42 est auMoins650 , avec un nombre moyen de coups = 8.54 ... - La stratégie classée # 9 / 42 est bernoulli_0.15, avec un nombre moyen de coups = 8.55 ... - La stratégie classée #10 / 42 est auMoins600 , avec un nombre moyen de coups = 8.56 ... - La stratégie classée #11 / 42 est auMoins350 , avec un nombre moyen de coups = 8.72 ... - La stratégie classée #12 / 42 est auMoins700 , avec un nombre moyen de coups = 8.74 ... - La stratégie classée #13 / 42 est auMoins300 , avec un nombre moyen de coups = 8.98 ... - La stratégie classée #14 / 42 est bernoulli_0.2, avec un nombre moyen de coups = 9.12 ... - La stratégie classée #15 / 42 est auMoins800 , avec un nombre moyen de coups = 9.22 ... - La stratégie classée #16 / 42 est auMoins850 , avec un nombre moyen de coups = 9.37 ... - La stratégie classée #17 / 42 est auMoins900 , avec un nombre moyen de coups = 9.44 ... - La stratégie classée #18 / 42 est auMoins250 , avec un nombre moyen de coups = 9.6 ... - La stratégie classée #19 / 42 est bernoulli_0.25, avec un nombre moyen de coups = 9.7 ... - La stratégie classée #20 / 42 est auMoins950 , avec un nombre moyen de coups = 9.9 ... - La stratégie classée #21 / 42 est auMoins1000, avec un nombre moyen de coups = 10.1 ... - La stratégie classée #22 / 42 est bernoulli_0.3, avec un nombre moyen de coups = 10.3 ... - La stratégie classée #23 / 42 est auMoins200 , avec un nombre moyen de coups = 10.4 ... - La stratégie classée #24 / 42 est bernoulli_0.35, avec un nombre moyen de coups = 10.8 ... - La stratégie classée #25 / 42 est bernoulli_0.4, avec un nombre moyen de coups = 11.1 ... - La stratégie classée #26 / 42 est bernoulli_0.45, avec un nombre moyen de coups = 11.7 ... - La stratégie classée #27 / 42 est auMoins150 , avec un nombre moyen de coups = 11.8 ... - La stratégie classée #28 / 42 est bernoulli_0.5, avec un nombre moyen de coups = 12.2 ... - La stratégie classée #29 / 42 est bernoulli_0.55, avec un nombre moyen de coups = 12.8 ... - La stratégie classée #30 / 42 est bernoulli_0.6, avec un nombre moyen de coups = 13.3 ... - La stratégie classée #31 / 42 est bernoulli_0.65, avec un nombre moyen de coups = 14 ... - La stratégie classée #32 / 42 est bernoulli_0.7, avec un nombre moyen de coups = 14.5 ... - La stratégie classée #33 / 42 est auMoins100 , avec un nombre moyen de coups = 14.6 ... - La stratégie classée #34 / 42 est bernoulli_0.75, avec un nombre moyen de coups = 14.9 ... - La stratégie classée #35 / 42 est bernoulli_0.8, avec un nombre moyen de coups = 15.7 ... - La stratégie classée #36 / 42 est bernoulli_0.85, avec un nombre moyen de coups = 16.1 ... - La stratégie classée #37 / 42 est bernoulli_0.9, avec un nombre moyen de coups = 16.7 ... - La stratégie classée #38 / 42 est bernoulli_0.95, avec un nombre moyen de coups = 17.3 ... - La stratégie classée #39 / 42 est auMoins50 , avec un nombre moyen de coups = 17.7 ... - La stratégie classée #40 / 42 est unCoup , avec un nombre moyen de coups = 17.7 ... - La stratégie classée #41 / 42 est bernoulli_1, avec un nombre moyen de coups = 17.8 ...
nb = 2000
totalMax = 3000
resultats = comparerStrategies(joueurs, nb=nb, total=totalMax)
print("Pour le total {} et {} simulations ...".format(totalMax, nb))
for (i, (n, j)) in enumerate(resultats):
print("- La stratégie classée #{:2} / {} est {:<14}, avec un nombre moyen de coups = {:.3g} ...".format(i, len(joueurs), j, n))
Pour le total 3000 et 2000 simulations ... - La stratégie classée # 0 / 42 est jusquauBout , avec un nombre moyen de coups = 8.66 ... - La stratégie classée # 1 / 42 est bernoulli_0 , avec un nombre moyen de coups = 9.48 ... - La stratégie classée # 2 / 42 est bernoulli_0.05, avec un nombre moyen de coups = 10.3 ... - La stratégie classée # 3 / 42 est bernoulli_0.1 , avec un nombre moyen de coups = 11.2 ... - La stratégie classée # 4 / 42 est auMoins550 , avec un nombre moyen de coups = 11.4 ... - La stratégie classée # 5 / 42 est auMoins600 , avec un nombre moyen de coups = 11.4 ... - La stratégie classée # 6 / 42 est auMoins500 , avec un nombre moyen de coups = 11.4 ... - La stratégie classée # 7 / 42 est auMoins650 , avec un nombre moyen de coups = 11.5 ... - La stratégie classée # 8 / 42 est auMoins700 , avec un nombre moyen de coups = 11.6 ... - La stratégie classée # 9 / 42 est auMoins450 , avec un nombre moyen de coups = 11.6 ... - La stratégie classée #10 / 42 est auMoins800 , avec un nombre moyen de coups = 11.7 ... - La stratégie classée #11 / 42 est bernoulli_0.15, avec un nombre moyen de coups = 11.8 ... - La stratégie classée #12 / 42 est auMoins400 , avec un nombre moyen de coups = 11.9 ... - La stratégie classée #13 / 42 est auMoins850 , avec un nombre moyen de coups = 12 ... - La stratégie classée #14 / 42 est auMoins950 , avec un nombre moyen de coups = 12.1 ... - La stratégie classée #15 / 42 est auMoins900 , avec un nombre moyen de coups = 12.2 ... - La stratégie classée #16 / 42 est auMoins350 , avec un nombre moyen de coups = 12.3 ... - La stratégie classée #17 / 42 est auMoins1000 , avec un nombre moyen de coups = 12.5 ... - La stratégie classée #18 / 42 est bernoulli_0.2 , avec un nombre moyen de coups = 12.7 ... - La stratégie classée #19 / 42 est auMoins300 , avec un nombre moyen de coups = 12.8 ... - La stratégie classée #20 / 42 est bernoulli_0.25, avec un nombre moyen de coups = 13.4 ... - La stratégie classée #21 / 42 est auMoins250 , avec un nombre moyen de coups = 13.8 ... - La stratégie classée #22 / 42 est bernoulli_0.3 , avec un nombre moyen de coups = 14.4 ... - La stratégie classée #23 / 42 est auMoins200 , avec un nombre moyen de coups = 15.1 ... - La stratégie classée #24 / 42 est bernoulli_0.35, avec un nombre moyen de coups = 15.1 ... - La stratégie classée #25 / 42 est bernoulli_0.4 , avec un nombre moyen de coups = 15.9 ... - La stratégie classée #26 / 42 est bernoulli_0.45, avec un nombre moyen de coups = 16.8 ... - La stratégie classée #27 / 42 est auMoins150 , avec un nombre moyen de coups = 17.3 ... - La stratégie classée #28 / 42 est bernoulli_0.5 , avec un nombre moyen de coups = 17.7 ... - La stratégie classée #29 / 42 est bernoulli_0.55, avec un nombre moyen de coups = 18.6 ... - La stratégie classée #30 / 42 est bernoulli_0.6 , avec un nombre moyen de coups = 19.4 ... - La stratégie classée #31 / 42 est bernoulli_0.65, avec un nombre moyen de coups = 20.3 ... - La stratégie classée #32 / 42 est bernoulli_0.7 , avec un nombre moyen de coups = 21.3 ... - La stratégie classée #33 / 42 est auMoins100 , avec un nombre moyen de coups = 21.6 ... - La stratégie classée #34 / 42 est bernoulli_0.75, avec un nombre moyen de coups = 22 ... - La stratégie classée #35 / 42 est bernoulli_0.8 , avec un nombre moyen de coups = 22.9 ... - La stratégie classée #36 / 42 est bernoulli_0.85, avec un nombre moyen de coups = 23.8 ... - La stratégie classée #37 / 42 est bernoulli_0.9 , avec un nombre moyen de coups = 24.5 ... - La stratégie classée #38 / 42 est bernoulli_0.95, avec un nombre moyen de coups = 25.3 ... - La stratégie classée #39 / 42 est auMoins50 , avec un nombre moyen de coups = 26.2 ... - La stratégie classée #40 / 42 est unCoup , avec un nombre moyen de coups = 26.4 ... - La stratégie classée #41 / 42 est bernoulli_1 , avec un nombre moyen de coups = 26.4 ...
nb = 1000
totalMax = 5000
resultats = comparerStrategies(joueurs, nb=nb, total=totalMax)
print("Pour le total {} et {} simulations ...".format(totalMax, nb))
for (i, (n, j)) in enumerate(resultats):
print("- La stratégie classée #{:2} / {} est {:<14}, avec un nombre moyen de coups = {:.3g} ...".format(i, len(joueurs), j, n))
Pour le total 5000 et 1000 simulations ... - La stratégie classée # 0 / 42 est jusquauBout , avec un nombre moyen de coups = 13.2 ... - La stratégie classée # 1 / 42 est bernoulli_0 , avec un nombre moyen de coups = 14.2 ... - La stratégie classée # 2 / 42 est bernoulli_0.05, avec un nombre moyen de coups = 15.6 ... - La stratégie classée # 3 / 42 est auMoins650 , avec un nombre moyen de coups = 16.9 ... - La stratégie classée # 4 / 42 est bernoulli_0.1 , avec un nombre moyen de coups = 17 ... - La stratégie classée # 5 / 42 est auMoins850 , avec un nombre moyen de coups = 17.1 ... - La stratégie classée # 6 / 42 est auMoins800 , avec un nombre moyen de coups = 17.1 ... - La stratégie classée # 7 / 42 est auMoins700 , avec un nombre moyen de coups = 17.1 ... - La stratégie classée # 8 / 42 est auMoins600 , avec un nombre moyen de coups = 17.2 ... - La stratégie classée # 9 / 42 est auMoins1000 , avec un nombre moyen de coups = 17.3 ... - La stratégie classée #10 / 42 est auMoins900 , avec un nombre moyen de coups = 17.3 ... - La stratégie classée #11 / 42 est auMoins950 , avec un nombre moyen de coups = 17.4 ... - La stratégie classée #12 / 42 est auMoins500 , avec un nombre moyen de coups = 17.5 ... - La stratégie classée #13 / 42 est auMoins550 , avec un nombre moyen de coups = 17.6 ... - La stratégie classée #14 / 42 est auMoins450 , avec un nombre moyen de coups = 18 ... - La stratégie classée #15 / 42 est bernoulli_0.15, avec un nombre moyen de coups = 18.2 ... - La stratégie classée #16 / 42 est auMoins400 , avec un nombre moyen de coups = 18.5 ... - La stratégie classée #17 / 42 est auMoins350 , avec un nombre moyen de coups = 19.3 ... - La stratégie classée #18 / 42 est bernoulli_0.2 , avec un nombre moyen de coups = 19.7 ... - La stratégie classée #19 / 42 est auMoins300 , avec un nombre moyen de coups = 20.2 ... - La stratégie classée #20 / 42 est bernoulli_0.25, avec un nombre moyen de coups = 21.2 ... - La stratégie classée #21 / 42 est auMoins250 , avec un nombre moyen de coups = 22.1 ... - La stratégie classée #22 / 42 est bernoulli_0.3 , avec un nombre moyen de coups = 22.7 ... - La stratégie classée #23 / 42 est bernoulli_0.35, avec un nombre moyen de coups = 23.7 ... - La stratégie classée #24 / 42 est auMoins200 , avec un nombre moyen de coups = 24.7 ... - La stratégie classée #25 / 42 est bernoulli_0.4 , avec un nombre moyen de coups = 25.3 ... - La stratégie classée #26 / 42 est bernoulli_0.45, avec un nombre moyen de coups = 27.2 ... - La stratégie classée #27 / 42 est auMoins150 , avec un nombre moyen de coups = 28.3 ... - La stratégie classée #28 / 42 est bernoulli_0.5 , avec un nombre moyen de coups = 28.6 ... - La stratégie classée #29 / 42 est bernoulli_0.55, avec un nombre moyen de coups = 29.8 ... - La stratégie classée #30 / 42 est bernoulli_0.6 , avec un nombre moyen de coups = 31.4 ... - La stratégie classée #31 / 42 est bernoulli_0.65, avec un nombre moyen de coups = 33 ... - La stratégie classée #32 / 42 est bernoulli_0.7 , avec un nombre moyen de coups = 34.2 ... - La stratégie classée #33 / 42 est auMoins100 , avec un nombre moyen de coups = 35.5 ... - La stratégie classée #34 / 42 est bernoulli_0.75, avec un nombre moyen de coups = 36 ... - La stratégie classée #35 / 42 est bernoulli_0.8 , avec un nombre moyen de coups = 37.3 ... - La stratégie classée #36 / 42 est bernoulli_0.85, avec un nombre moyen de coups = 38.8 ... - La stratégie classée #37 / 42 est bernoulli_0.9 , avec un nombre moyen de coups = 40.5 ... - La stratégie classée #38 / 42 est bernoulli_0.95, avec un nombre moyen de coups = 41.6 ... - La stratégie classée #39 / 42 est auMoins50 , avec un nombre moyen de coups = 42.9 ... - La stratégie classée #40 / 42 est bernoulli_1 , avec un nombre moyen de coups = 43.1 ... - La stratégie classée #41 / 42 est unCoup , avec un nombre moyen de coups = 43.2 ...
$\implies$ la stratégie la plus efficace est en effet jusquauBout
!
Notons néanmoins que je n'ai testé que des stratégies très simples... En particulier, celles considérées n'utilisent pas, dans leur prise de décision, le nombre de coups déja joué, ni le nombre de tirage courant.