Aléatoire : test du poker | effectifs vers probabilités

Aide à la résolution d'exercices de mathématiques de tout niveau scolaire.
[participation réservée aux utilisateurs inscrits]
Règles du forum
Merci de soigner la rédaction de vos messages et de consulter ce sujet avant de poster. Pensez également à utiliser la fonction recherche du forum.
SimonPaulL

Aléatoire : test du poker | effectifs vers probabilités

Message non lu par SimonPaulL »

Bonsoir tout le monde !

Dans le cadres de mon TPE, je suis amené à faire le test du poker sur la fonction randint() de python.

Ce test travail par bloc de 4 nombres qu'il classe dans une des catégorie suivante :
- les quatres chiffres sont différents. probabilité = 0,504
- il y a une pair et deux chiffres différents. probabilité=0,432
- il y a deux pair. probabilité=0,027
- il y a 3 chiffres identiques. probabilité=0,036
- il y a 4 chiffres identiques. probabilité=0,001
Ce lien explique comment il est réalisé et explique d'où viennent les probabilitées : https://univers-ti-nspire.fr/files/pdf/ ... -TNS21.pdf

J'arrive très bien a avoir une liste final avec le nombre de fois qu’apparaît chaque configuration mais je n'arrive pas à en tiré les probabilités.
Les chiffres que je trouve sont très loin des probabilité théoriques auquel c'est sensé se rapproché.
Voici l'algorithme écris sur le lien précédent : https://www.noelshack.com/2018-05-3-151 ... 201427.png

Et voici mon code actuel écris en python :

Code : Tout sélectionner

from random import randint
from functools import reduce
from operator import mul

def poker(nbChiffre=1000):
	'''Test du poker'''
	count = {"AAAA":0,"AAAB":0,"AABB":0,"AABC":0,"ABCD":0}
	values = [[randint(0,9),randint(0,9),randint(0,9),randint(0,9)] for i in range(nbChiffre//4)] # Je remplis une liste de paquet contenant 4 chiffres aléatoires
	for paquet in values:
               # Je test la configuration du paquet et j'ajoute un a la clé correspondante dans le dictionnaire
		paquet = [paquet.count(valeurPaquet) for valeurPaquet in paquet] 
		paquet = reduce(mul,paquet)
		if paquet == 1:
			count["ABCD"]+=1
		elif paquet == 4:
			count["AABC"]+=1
		elif paquet == 16:
			count["AABB"]+=1
		elif paquet == 27:
			count["AAAB"]+=1
		elif paquet == 256:
			count["AAAA"]+=1
	return count # retourne le dictionnaire avec les effectifs pour chaque configuration (donc pas une probabilité)
Voilà j'espère que vous pourrais l'aider a comprendre comment passé des effectifs au probabilité.
Merci par avance de votre aide,
Simon
rebouxo
Modérateur honoraire
Modérateur honoraire
Messages : 6962
Inscription : mercredi 15 février 2006, 13:18
Localisation : le havre

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par rebouxo »

Que fait reduce ? Que fait mul ?
Olivier
A line is a point that went for a walk. Paul Klee.
Par solidarité, pas de MP.
SimonPaulL

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par SimonPaulL »

rebouxo a écrit :Que fait reduce ? Que fait mul ?
Olivier
Je ne sais pas ce que fait reduce en temps normal mais dans ce cas ci, reduce(mul, une_liste) mais multiplier tout les termes de la liste entre eux. Cela permet d'avoir un nombre unique lié à la configuration pour pouvoir la reconnaître.

EDIT : La fonction reduce applique en faite une fonction (ici mul, la multiplication) au premier et second élement de la liste, puis au résultat obtenu avec le troisème élement et ainsi de suite jusqu'à ce qu'il ne reste plus d'un seul nombre.
Cette fonction vient du paquet functools
rebouxo
Modérateur honoraire
Modérateur honoraire
Messages : 6962
Inscription : mercredi 15 février 2006, 13:18
Localisation : le havre

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par rebouxo »

J'ai abondamment commenté ton code. Maintenant je suis à peu près persuadé qu'il fait ce que tu cherches à faire.
Cela dit je ne vois pas pourquoi tu n'utilises pas des noms différents pour tes variables (et des noms plus explicites).
Tu simules 1000 mains, pourquoi alors diviser par le nombre de cartes distribuées ?
C'est bien pratique de regarder le contenu des différentes variables.

Code : Tout sélectionner

from random import randint
from functools import reduce
from operator import mul

def poker(nbChiffre=1000):
    '''
    Test du poker Construit 1000 mains de poker, 
    puis tests si les mains sont constituées de la même
    carte, ou d'un brelan de 2 pairs, 4 cartes identiques
    '''
    count = {"AAAA":0,"AAAB":0,"AABB":0,"AABC":0,"ABCD":0}
    # Je remplis une liste de paquet contenant 4 chiffres aléatoires
    ## pourquoi ne pas pas partir sur 1000 mains au lieu de 250 ?
    values = [[randint(0,9),randint(0,9),randint(0,9),randint(0,9)] for i in range(nbChiffre)]
    for paquet in values: ## pourquoi paquet au lieu de main
        print(paquet,reduce(mul,paquet))
        # Je test la configuration du paquet et j'ajoute un a la clé correspondante dans le dictionnaire
        ## tu utilises un paquet (une main) de tes 1000 tirages
        ## et tu réécris tout de suite dessus.
        ## C'est voulu ?
        ## Que fais-tu ici ?
        paquet = [paquet.count(valeurPaquet) for valeurPaquet in paquet]
        print(paquet)
        ## Pareil pourquoi garder le même nom ?
        paquet = reduce(mul,paquet) ## pourquoi pas typeMain ?
        print(paquet)
        if paquet == 1:
            count["ABCD"]+=1
        elif paquet == 4:
            count["AABC"]+=1
        elif paquet == 16:
            count["AABB"]+=1
        elif paquet == 27:
            count["AAAB"]+=1
        elif paquet == 256:
            count["AAAA"]+=1
        # retourne le dictionnaire avec les effectifs pour chaque configuration
        #(donc pas une probabilité)
    return count 

print poker(10)
A line is a point that went for a walk. Paul Klee.
Par solidarité, pas de MP.
SimonPaulL

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par SimonPaulL »

Bonjour et merci de ton aide.

1) Il est vrai que 1000 mains est mieux que seulement 250 mains. En faite, j'avais raisonné sur le nombre de chiffres (raisonnement faux). Dans mon doc final, je l'avais fait avec 1 million de chiffres (donc 250000 mains)

2) J'ai appelé paquet au lieux de mains de façon arbitraire, les deux fonctionnes mais tu as raison qu'avec "poker" on à tendance à penser "main"

3) Ce que je réécris dessus c'est en faite le nombre de fois où la valeurs apparaît dans la mains. Donc [7,7,7,3] devient [3,3,3,1] par exemple. C'est le rôle de :

Code : Tout sélectionner

paquet = [paquet.count(valeurPaquet) for valeurPaquet in paquet]
Ensuite je les multiplies entre eux pour avoir un identifiant unique de la configuration : 3*3*3*1=27 donc la configuration AAAB. C'est le rôle de :

Code : Tout sélectionner

paquet = reduce(mul,paquet)
Tu as raisons que pour la lisibilité du code, il vaudrait mieux que je mette typeMain. J'avais bêtement réfléchi sur le nombre de variables que j'utilise. Quand j'écris par dessus à partir de la valeurs précédente, c'est parce que je n'ai justement plus besoin de la valeur précédente (c'est pourquoi ma variable s'appelle paquet tout au long de la boucle)

4) Et c'est justement là que tu touches le cœur du problème : je me retrouve avec des effectifs alors que je veux des probabilités. J'ai pensé dans un premier temps qu'il fallait diviser chaque valeurs du dictionnaire par le nombre de chiffre total. Mais cela ne correspond pas au valeurs que je suis sensé trouver et je ne sais pas par quoi diviser. Cela dit, l'ordre de grandeur est respecté quand je divise chaque valeurs par le nombre de chiffre (ABCD>AABC>AAAB>AABB>AAAA)

Mon problème est donc bien de trouver comment passer des effectifs aux probabilités...
Merci de tes conseil cela va améliorer la compréhension.
Simon.
rebouxo
Modérateur honoraire
Modérateur honoraire
Messages : 6962
Inscription : mercredi 15 février 2006, 13:18
Localisation : le havre

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par rebouxo »

Ben c'est là que le nombre de tirage est important. Si tu as 1000 mains, tes valeurs sont conformes à ce que tu attends (enfin sur un essai). Les probas se faisant par rapport aux mains et non aux cartes distribuées. C'est bien les différents types de mains que tu étudies ?

Je ne suis pas certain que de réécrire dans des variables parce que l'on n'en a plus besoin soit une très bonne idée. Certes tu économises quelques octets, mais la lisibilité du code est catastrophique.

Personnellement sur ton code, je lui reproche sa mauvaise lisibilité. C'est du au peu de commentaires et aussi au fait que tu réutilises des variables. Très clairement, j'aurais pris : main pour paquet, puis cartes pour paquet, enfin le dernier je l'aurais appelé type ou discriminant (très clairement cela discrimine ta main).

Les probas en découlent immédiatement.

Olivier
A line is a point that went for a walk. Paul Klee.
Par solidarité, pas de MP.
SimonPaulL

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par SimonPaulL »

Je te remercie beaucoup celà fonctionne !

Je vais modifié mon code suite à tes conseil. En effet je ne l'avais pas commenté pour moi par soucis de timing et je ne l'ai fait que dans mon document final.
Je vais aller changer le nom des variables et commenter tout ça de suite :D

Encore merci à toi Olivier et bonne continuation :)
Cordialement,
Simon.
MB
Administrateur
Administrateur
Messages : 8096
Inscription : samedi 28 mai 2005, 14:23
Statut actuel : Enseignant

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par MB »

SimonPaulL a écrit :4) Et c'est justement là que tu touches le cœur du problème : je me retrouve avec des effectifs alors que je veux des probabilités. J'ai pensé dans un premier temps qu'il fallait diviser chaque valeurs du dictionnaire par le nombre de chiffre total. Mais cela ne correspond pas au valeurs que je suis sensé trouver et je ne sais pas par quoi diviser.
Il faut bien effectuer cette division. Par exemple en remplaçant la dernière commande par la suivante.

Code : Tout sélectionner

return {k:v/nbChiffre for k,v in count.items()}
En faisant une tentative avec nbChiffre valant 50000 et j'ai trouvé.

Code : Tout sélectionner

{'AAAA': 0.00082, 'AAAB': 0.03612, 'AABB': 0.02784, 'AABC': 0.4305, 'ABCD': 0.50472}
MB. Rejoignez notre partenaire pCloud et bénéficiez de 10Go de stockage gratuits ou d'une offre premium !
Pas d'aide en message privé. Merci de consulter ce sujet avant de poster votre premier message.
SimonPaulL

Re: Aléatoire : test du poker | effectifs vers probabilités

Message non lu par SimonPaulL »

Entre temps j'ai modifié mon code pour qu'il fasse les probabilités :

Code : Tout sélectionner

from random import randint
from functools import reduce
from operator import mul
from decimal import Decimal as d

compteur = {"AAAA":0,"AAAB":0,"AABB":0,"AABC":0,"ABCD":0}
# On crée une liste de n mains de 4 chiffres
listeMains = [[randint(0,9),randint(0,9),randint(0,9),randint(0,9)] for i in range(n)]
for main in listeMains:
  # On remplace chaque valeur par le nombre de fois que cette valeur existe dans la main
  typeConfig = [main.count(carte) for carte in main]
  typeConfig = reduce(mul, typeMain) # On multiplie chaque nombre entre eux
  # On traîte chaque cas
  if typeConfig == 1:
    compteur["ABCD"]+=1
  elif typeConfig == 4:
    compteur["AABC"]+=1
  elif typeConfig == 16:
    compteur["AABB"]+=1
  elif typeConfig == 27:
    compteur["AAAB"]+=1
  elif typeConfig == 256:
    compteur["AAAA"]+=1
# Enfin, on passe des effectifs au probabilités
for config,valeur in compteur.items():
  compteur[config] = valeur/nbChiffre
return compteur
Et je préférerais sans doute cette façon de faire les probabilités (voir ma dernière boucle for) car je la pense plus lisible (remarque je ne m'avance pas trop sur la lisibilité de mon code :lol: )

Néanmoins je te remercie MB car je ne connaissais pas du tout cette syntaxe ! Enfin je la connaissais pour les listes mais pas pour les dico...
Je vais changer avec ta façon dans le code source qui sera disponible avec mon dossier final.
Et oui c'est exactement ce que je dois trouver :D

Encore merci à vous deux,
Simon.