Simulación de Montecarlo para Probabilidades en Juegos de Cartas
Resumen
¡Hola! ¿Cómo van con el reto? Noten que cuando digo "barajas" me refiero a los "naipes/cartas" individuales. Puede darse el caso de que en algunos países la palabra "baraja" sea sinónimo de "mazo", pero en esta clase no es así, siempre me estoy refiriendo a los elementos de forma individual.
Simulación de Montecarlo para Probabilidades en Juegos de Cartas
Amigos muchas gracias por el codigo, no he visto la clase pero me llamó mucho la atención tu comentario y ahora voy a leer tu código :)
¡Reto completado! Función para determinar la probabilidad de encontrar una escalera de color (lo que el profe llama corrida) en una mano. Notar que se necesitan muchas simulaciones para acercarse a la probabilidad real (0,14%) debido a que ya de por sí la probabilidad es bajísima:
defescalera_color(tamano_mano, intentos):# Creamos una baraja de cartas cartas = crear_baraja()# Creamos tantas manos como nos indicó el usuario manos =[]for _ inrange(intentos): mano = obtener_mano(cartas, tamano_mano) manos.append(mano) escaleras =0for mano in manos:# Creamos una lista con todos los palos de la mano palos =[carta[0]for carta in mano] valores =[]# Creamos un conjunto para eliminar los elementos repetidos, y preguntamos si la# longitud de este conjunto es igual a 1 (es decir, todas las cartas son del mismo palo)iflen(set(palos))==1:for carta in mano:# Convertimos las cartas a listas, para poder manipularlas carta =list(carta)# Convertimos las letras a números, para evaluar posteriormente la escalera de colorif carta[1]=='A': carta[1]='1'if carta[1]=='J': carta[1]='11'if carta[1]=='Q': carta[1]='12'if carta[1]=='K': carta[1]='13'# Transformamos los valores en str a int, para facilitar la comparación posterior carta[1]=int(carta[1]) valores.append(carta[1])# Ordenamos los valores valores.sort() es_escalera =True# Comprobamos que todos los valores sean consecutivosfor i, valor inenumerate(valores):if i !=0:if valor - valores[i-1]!=1: es_escalera =Falsebreak# Si todo se cumplió, sumamos uno al contador de escalerasif es_escalera: escaleras +=1print(f'Escaleras: {escaleras}') probabilidad_de_encontrar_escalera =(escaleras / intentos)*100print(f'La probabilidad de encontrar una escalera de color en una mano de {tamano_mano} cartas es de {probabilidad_de_encontrar_escalera}%')
Excelente logica, me parece que el codigo se podria limpiar un poco más cambiando los if anidados por un diccionario, ademas se ahorraria el tener que pasarlos a int luego. Pero eso seria todo
excelente resolución compañero, te quedo muy bien
Aqui dejo un algoritmo que saca la probabilidad De la jerarquia del poker.
Este fue el resultado que obtuve:
Luego de un Millon de intentos se obtujo este resultado. de un Millon de intento Una sola Escalera Real
Siente Muy Afortunado si alguna vez te a salido Saludos
Probabilidad de Par: 0.471806
Probabilidad de Doble Par: 0.047398
Probabilidad de Trio: 0.022473
Probabilidad de Poker: 0.000243
Probabilidad de Full House: 0.001419
Probabilidad de Color: 0.002055
Probabilidad de Escalera: 0.003924
Probabilidad de Escalera Color: 9e-06
Probabilidad de Escalera_Real: 1e-06
import random
import collections
PINTA=["pica","corazon","trebol","diamante"]VALOR=[1,2,3,4,5,6,7,8,9,10,11,12,13]manos=[]def crear_baraja(): barajas=[]for pinta inPINTA:for valor inVALOR: barajas.append((pinta,valor))return barajas
def obtener_mano(barajas, tamano_mano): mano= random.sample(barajas,tamano_mano)return mano
def can_manos(intentos):for _ inrange(intentos): mano=obtener_mano(barajas,tamano_mano) manos.append(mano)def main(manos): doble_par=0 pares=0 trio=0 poker=0 full_house=0 escalera=0 escaleram=0 color=0 escalera_color=0 escalera_real=0for mano inmanos: valores=[] pintas=[]for carta inmano: valores.append(carta[1]) pintas.append(carta[0]) counter=dict(collections.Counter(valores)) counter_pintas=dict(collections.Counter(pintas)) minando_escalera=sorted(list(dict(collections.Counter(valores)).keys())) def escalera_funcion(minando_escalera): esc=False escr=False # Identificando si tenemos escapera
iflen(minando_escalera)==5:if(abs(minando_escalera[0]-minando_escalera[4])==4): esc=Trueif(minando_escalera[0]==1):if(minando_escalera[1]==10)&(abs(minando_escalera[1]-minando_escalera[4])==3): escr=Truereturn esc,escr
def color_funcion(counter_pintas): # Identificando si hay Color cr=Falseiflen(counter_pintas)==1: cr=Truereturn cr
def valor_pareja(counter): # Funcion que ClasificaLosValores par, doble par,Trio,Poker y FullHouse c=False dob_par=False par=False pok=False tr=False fh=Falsefor val in counter.values(): # ClasificandoPokerif val==4: pok=True # ClasificandoTrioif val==3: tr=True # ClasificandoDobleParif(val==2)&(c==True): dob_par=True # ClasificandoParif(val==2)&(c==False): par=True c=True # ClasificandoFullHouseif(tr==True)&(c==True): fh=Truereturn pok,fh,tr,par, dob_par
# contadores de pares, poker, doble, trio, full house
counter_pares=valor_pareja(counter) doble_par=doble_par+counter_pares[4] pares=pares+counter_pares[3] trio=trio+counter_pares[2] full_house=full_house+counter_pares[1] poker=poker+counter_pares[0]
# contadores escalera
contador_escaleras=escalera_funcion(minando_escalera) escalera=escalera+contador_escaleras[0]+contador_escaleras[1] # # contador Color contado_color=color_funcion(counter_pintas) color=color+contado_color
# IndentificandoEscaleraRealif(contador_escaleras[1]==True)&(contado_color==True): escalera_real+=1print(f"Aparecio la mano Milagrosa {mano}")if(contador_escaleras[0]==True)&(contado_color==True): escalera_color+=1print(f"Escalera color {mano}")return pares, doble_par, trio,poker,full_house,color,escalera,escalera_color,escalera_real
if __name__=="__main__": tamano_mano=5 intentos=int(input("cuantos numeros de intentos")) barajas=crear_baraja() manos_1=can_manos(intentos) probabilidades=main(manos) j=["Par","Doble Par","Trio","Poker","Full House","Color","Escalera","Escalera Color","Escalera_Real"]for i inrange(len(probabilidades)):print(f"Probabilidad de {j[i]}: {probabilidades[i]/intentos}")```
Gracias por compartir tu solución Juan
Interesante solución, pero siendo honesto no me gusta demasiado cómo abreviaste las variables...
tengo entendido que uno de los principios del Python es hacerlo legible y usar también espaciados y demás... al no tener espacios ni nada, se hace complicado leer el código a simple vista...
quizá te pueda ayudar espiar PEP 8 -- Style Guide for Python Code donde están definidos las reglas generales del espaciado y las variables y demás...
espero no moleste mi comentario, pero me chocó al leerlo... suerte...
Aqui está el reto :D!! Me gustó hacerlo e incluso apliqué sort merge para ordenar la lista y comparar de forma más eficaz :D!
import random
import collections
PALOS=['espada','corazon','rombo','trebol']VALORES=[1,2,3,4,5,6,7,8,8,9,10,11,12,13]def crear_baraja(): barajas =[]for palo inPALOS:for valor inVALORES: barajas.append((palo,valor))return barajas
def obtener_mano(barajas,tamaño_mano): mano = random.sample(barajas,tamaño_mano)return mano
def main(tamaño_mano,intentos): barajas =crear_baraja() manos =[]for _ inrange(intentos): mano =obtener_mano(barajas,tamaño_mano) manos.append(mano) pares =0for mano inmanos: valores =[]for carta inmano: valores.append(carta[1]) counter =dict(collections.Counter(valores))for val in counter.values():if val==2: pares +=1break probabilidades=pares/intentos
print(f'La probabilidad de obtener un par en una mano de {tamaño_mano} barajas es {probabilidades} ') pass
def simulacion_corrida(tamaño_mano_corrida,intentos): barajas_2 =crear_baraja() manos =[]for _ inrange(intentos): mano_corrida =obtener_mano(barajas_2,tamaño_mano_corrida) manos.append(mano_corrida) corridas=0for mano inmanos: valores =[]for carta inmano: valores.append(carta[1]) contador =dict(collections.Counter(valores)) valores_sorted=sort_merge(valores) i=0while((valores_sorted[i]-valores_sorted[i+1])==-1): i+=1if i==len(valores_sorted)-1: corridas+=1break probability_corridas=corridas/intentos
print(f'La probabilidad de obtener una corrida en una mano de {tamaño_mano_corrida} barajas es {probability_corridas} ') pass
def sort_merge(lista):iflen(lista)>1: #Dividing these lists until we get every list with1 element
middle =len(lista)//2 left_list = lista[:middle] right_list = lista[middle:]sort_merge(left_list)sort_merge(right_list) #After having 1 element list we have to join them in order
#Iterators i=0 j=0 #Iteratorsfor the main list
k=0whilelen(left_list)>i and len(right_list)>j:if left_list[i]>right_list[j]: lista[k]=right_list[j] j+=1else: lista[k]=left_list[i] i+=1 k+=1whilelen(left_list)>i: lista[k]= right_list[i] i+=1 i +=1 k +=1whilelen(right_list)>j: lista[k]=right_list[j] j+=1 k+=1return lista
if __name__ =="__main__": tamaño_mano =int(input("¿Cuantas barajas será la mano?: ")) intentos =int(input('¿Cuantos intentos?: '))main(tamaño_mano,intentos) tamaño_mano_corrida =int(input("¿Cuantas barajas será la mano de corrida?: "))simulacion_corrida(tamaño_mano_corrida, intentos)
Después de postear mi solución al reto, miré tu solución que también esta super bien resuelta. Si te apetece mirar mi solución esta justo en el post después del tuyo. Intenté no modificar las constantes que puso el profe en la clase y agrege alguna forma diferente para saber si se trata de una escalera o no.
Well done maannn! ;)
Holaa Raul! Gracias por comentar y ver mi solucíón
Tambien pude ver la tuya y me parece muy ingenioso por separar la forma de como corroboraste la escalera, tu solo utilizaste al primero y al último yo probe con todos en un while! Implementare esa forma tuya y tambien cuando hiciste la tupla de 3 para evitar cambiar la lista!! Muy ingenioso :D!!! Bien hecho tambien :D!!
Una corrida es una escalera ?
Si, La escalera (straight) es una combinación de cinco cartas consecutivas, no necesariamente del mismo palo.
Exactamente
Mi aporte matemático, será el calculo de la probabilidad de manera analítica para compararla con la que da la simulación.
Si la mano es de 5 cartas, la probabilidad de que se obtenga un solo par se obtiene usando varias combinatorias. Recuerden que en estas el orden no importa, ya que dentro de mis cartas tener un orden entre las mismas no tiene importancia
C52,5 = numero de manos distintas de 5 cartas
C13,1= numero de maneras de extraer una carta de un mismo palo
C4,2 = numero de maneras de elegir 2 palos de 4 que hay
C12,3 = numero de maneras de extraer tres cartas ya que dos serian del mismo tipo(por eso es un par)
probabilidad un par = (C13,1C4,2C12,3*4^3)/C52,5 = (13x6x220x64)/2598960 = 0.422569
excelente análisis matematico muchas gracias por compartirlo
De cuantas barajas sera la mano? 5
Cuantos intentos para calcular la probabilidad? 10.000.000
par: 0.4714778
doble par: 0.0475021
trio: 0.0225424
escalera: 0.0039482
color: 0.0019907
full house: 0.0014463
poker: 0.0002462
escalera color: 1.4e-05
escalera real: 1.2e-06
genial corriste las probabilidades en los códigos
Fue muy interesante el reto, me di cuenta que asignando j q k a 11, 12, 13 todas las escaleras sumaban un multiplo de 5 y como son 5 cartas siempre la resta de la mayor menos la menor será 4. Con esas dos condiciones podemos saber si hay una escalera iniciando en cualquier número, lo implemente con esta comprobación:
(Modifique el codigo presentado y no use un diccionario sino como lista)
def main(tamano_mano, intentos): barajas =crear_baraja() manos =[]for _ inrange(intentos): mano =obtener_mano(barajas, tamano_mano) manos.append(mano) pares =0for mano inmanos: valores =[]for carta inmano: valores.append(carta[1])for val invalores:ifint(valores[4])-int(valores[0])==4and(int(valores[0])+int(valores[1])+int(valores[2])+int(valores[3])+int(valores[4]))%5==0: pares +=1break probabilidad_par = pares / intentos
print(f'La probabilidad de obtener una en una mano de {tamano_mano} barajas es {probabilidad_par}')
[1, 4, 5, 5, 5]
Te pongo de ejemplo esta lista(mano), cumple tus dos condiciones. Pero no hay una escalera.
extra: sum(valores[0:5]) % 5 == 0 ( asi es una forma mas corta de poner la segunda condicion, recibiendo valores type int )
Hey, gracias por el feedback, será plantearlo entonces con una condidión de límite, pues cada escalera su suma da un valor diferente de suma multiplo de 5, se crearía una verificación adicional pero serviria.
Lo de acortar la segunda condición si lo pense pero no retornaba un int.
import random
import collections
import copy
PALOS=['Espada','Corazón','Pica','Trébol']VALORES=['As','2','3','4','5','6','7','8','9','10','J','Q','K']def crear_baraja(): barajas =[]for palo inPALOS:for valor inVALORES: barajas.append((palo, valor))return barajas
def obtener_mano(baraja, tamano_mano):return random.sample(baraja, tamano_mano)def hallar_probabilidad_corrida(manos, tamano_mano, cantidad_simulaciones): corridas =0for mano inmanos: valores =[] # Obtener valor numerico de cada carta
for carta inmano:try: valor =int(carta[1]) except ValueError: switcher ={'As':1,'J':11,'Q':12,'K':13} valor = switcher[carta[1]] valores.append(valor) valores.sort() # Comprobar si es una corrida
anterior = valores[0]for valor in valores[1:]: esCorrida =(anterior +1)== valor
if not esCorrida:breakelse: anterior = copy.copy(valor) # Contar si es corrida
ifesCorrida: corridas +=1 probabilidad = corridas / cantidad_simulaciones
print(f'La probablilidad de tener una corrida de {tamano_mano} cartas es {probabilidad}')def main(tamano_mano, cantidad_simulaciones): baraja =crear_baraja() manos =[]for _ inrange(cantidad_simulaciones): mano =obtener_mano(baraja, tamano_mano) manos.append(mano)hallar_probabilidad_corrida(manos, tamano_mano, cantidad_simulaciones)if __name__ =='__main__': tamano_mano =int(input('Cuántas cartas tendrá cada mano: ')) cantidad_simulaciones =int(input('Cuántas simulaciones debo correr? '))main(tamano_mano, cantidad_simulaciones)
Hola Samuel. Podrias explicarme que haces en la seccion '#Comprobar si es una corrida'. No conozco la funcion copy que utilizas.
@lucianonicolaspereira
Un par de cosas a tener en cuenta para cuando el programa llega a esa seccion:
La lista esta conformada por numeros enteros, donde por ejemplo As = 1 y rey = 13
La lista esta ordenada de menor a mayor
En esa seccion:
Guardo el primer valor en mi variable auxiliar, que uso para comparar el valor de un elemento de la lista con el valor del elemento inmediatamente anterior
anterior = valores[0]
Recorro la lista desde el segundo elemento al ultimo, porque el primero ya lo guardé
for valor in valores[1:]:
El [1:] indica que se usa la lista a partir del indice 1
Compruebo que cada valor sea el numero consecutivo del valor que posee el elemento anterior en la lista
esCorrida =(anterior +1)== valor
Si el valor del elemento actual no es el consecutivo del elemento anterior, ya no me interesa seguir analizando la lista. Si es el valor consecutivo, guardo el valor actual para compararlo con el proximo elemento.
if not esCorrida:breakelse: anterior = copy.copy(valor)
copy.copy() es una funcion de python que te permite copiar el objeto de una variable con la variable anterior. Pasa que las variables de python no guardan valores como otros lenguajes, sino que guardan referencias a objetos, entonces para copiar el valor de una variable a otra variable hay que usar esa funcion. Igual puede que la haya usado mal en este caso, todavia no lo entiendo del todo.
Aca te dejo algo para que leas sobre lo que te digo de las variables:
Variables en python
Funciones copy
Hola tengo una duda, actualmente tengo una doble lista de tuplas cuando imprimo la mano, como hago para pasar esta doble lista de tuplas a un diccionario???
De lo que comprendo de tu pregunta podrías ocupar algo así
<tupla =((8,'espadas'),(4,'corazones'))dict(t)#Te entregara algo así
{1:'a',2:'b'}>
.
Hola.
En el mismo problema tuve el mismo dilema que tú, pero llegué a una solución un poco más simple en mi concepto, pero igualmente funcional, usar los valores(variable como tal) generados en el primer for loop.
Saludos.
Tengo una pregunta referente a python. Escribí una función que compara si una mano(de cartas de Uno) esta contenida dentro de otra. La función es la siguiente:
def match_hands(compare_hand, reference_hand): _compare_hand =list(compare_hand) _reference_hand =list(reference_hand)print(f"hand id (entering comparison): {id(_compare_hand)}") initial_cards_count ={"compare":len(_compare_hand),"reference":len(_reference_hand)}if initial_cards_count["compare"]> initial_cards_count["reference"]:returnFalsewhile_compare_hand:try: _reference_hand.remove(_compare_hand.pop()) except ValueError: pass
if(len(_reference_hand)+ initial_cards_count["compare"])== initial_cards_count["reference"]: # All cards from compare_hand existed in reference_hand and where removed.returnTruereturnFalse
Como ven, los argumentos de la función son dos listas, las cuales son mutables. Dado que mi algoritmo remueve objetos dentro de las listas, pero no quiero que las listas originales, pasadas como argumentos, se modifiquen. Por ende, las he copiado y manipulo unicamente las copias:
Mi pregunta puntual es: Conocen una convención para usar con los nombre de las copias de los argumentos? Aca yo uso el mismo nombre agregando un "_" al comienzo (No se si sea lo correcto. La idea viene de la convención para definir internal members en clases). No quiero cambiar el nombre a algo diferente, dado que en si mismo es ya explicativo del significado y proposito de mis argumentos respecto de su contenido y de la función que los recibe.
Si fuera c++ usaría:
type function(cons& type argument)
y listo. No me vería en el problema descrito. En python esto no es posible por lo que me imagino que debe existir alguna convención al respecto.
Muchas gracias por su feedback.
Hola, @andresgre. 🤓
Para estos casos puedes usar la barra hacia abajo como estás ocupando. Es convención para “uso interno” débil.
En la guía de estilos PEP8 de Python puedes encontrar más de esto. 🐍
Hola, @datormx
Gracias por tu respuesta. Voy a revisar la guia de estilos que me compartes. Sin duda es un buen recurso.
que es una corrida? (quiero hacer el reto)
Se refiere a la escalera con todas las cartas del mismo color. La corrida real o escalera imperial es la menos probable y se conforma por la escalera de AS, K, Q, J y 10
Una corrida es el conjunto de 5 cartas consecutivas, en el poker hay 3 tipos de corridas o escaleras:
Escalera (5 cartas consecutivas, sin importar el palo)
Escalera de color (Aunque su nombre lo diga, no se refiere a que sean del mismo color, sino del mismo palo)
Escalera Imperial (10,J,Q,K,A del mismo palo (La mano más valiosa en el poker))
Hice casi todas las manos posibles, así quedaron mis probabilidades a 5 cartas y 100,000 intentos:
The **PAIR **probability for the hand size 5 is 0.46998
The TWO PAIR probability for the hand size 5 is 0.04705
The THREE OF A KIND probability for the hand size 5 is 0.02216
The **STRAIGHT **probability for the hand size 5 is 0.00369
The **FLUSH **probability for the hand size 5 is 0.00199
The FULL HOUSE probability for the hand size 5 is 0.00127
The **POKER **probability for the hand size 5 is 0.00026
The STRAIGHT FLUSH probability for the hand size 5 is 2e-05
import random
import collections
SUITS=['espada','corazon','rombo','trebol']VALUES=[i for i inrange(1,14)]def create_deck(): decks =[]for deck inSUITS:for value inVALUES: decks.append(( deck, value ))return decks
def get_hand(decks, hand_size): hand = random.sample(decks, hand_size)return hand
def is_straight(values):"""Compare two list: sorted input list vs newlist created as a range with the min and max value"""
returnsorted(values)==list(range(min(values),max(values)+1))def main(hand_size, attemps): #Variables... pair_flag =False trio_flag =False flush_flag =False straight_flag =False pairs =0 two_pairs =0 trio =0 straight =0 flush =0 full_house =0 straight_flush =0 poker =0 decks =create_deck() hands =[] #Create hands...for _ inrange(attemps): hand =get_hand(decks, hand_size) hands.append(hand) #Loop over the hands to find the probabilities
for hand inhands: values =[] suits =[]for card inhand: values.append(card[1]) suits.append(card[0]) counter_values =dict(collections.Counter(values)) counter_suits =dict(collections.Counter(suits)) pair_flag =False trio_flag =False flush_flag =False straight_flag =False #PAIR,TWOPAIR,TRIPS and POKERfor val in counter_values.values():if val ==2:ifpair_flag: two_pairs +=1else: pairs +=1 pair_flag =Trueif val ==3: trio +=1 trio_flag =Trueif val ==4: poker +=1 #FLUSHfor val in counter_suits.values():if val == hand_size: flush +=1 flush_flag =Truebreak #FULLHOUSE:We need a pair and a Threeof a kind
if pair_flag and trio_flag: full_house +=1 #STRAIGHT:Consecutives values
ifis_straight(values): straight +=1 straight_flag =True #STRAIGHTFLUSH:Straight+Flushif straight_flag and flush_flag: straight_flush +=1print(f'The PAIR probability for the hand size {hand_size} is {pairs / attemps}')print(f'The TWO PAIR probability for the hand size {hand_size} is {two_pairs / attemps}')print(f'The THREE OF A KIND probability for the hand size {hand_size} is {trio / attemps}')print(f'The STRAIGHT probability for the hand size {hand_size} is {straight / attemps}')print(f'The FLUSH probability for the hand size {hand_size} is {flush / attemps}')print(f'The FULL HOUSE probability for the hand size {hand_size} is {full_house / attemps}')print(f'The POKER probability for the hand size {hand_size} is {poker / attemps}')print(f'The STRAIGHT FLUSH probability for the hand size {hand_size} is {straight_flush / attemps}')if __name__ =="__main__": hand_size =int(input('Size Hand:')) attemps =int(input('Attemps:'))main(hand_size, attemps)
MI solución a la probabilidad de corrida
corrida=0if tamano_mano <5:print('la probabilidad de obtener una corrida es 0')else:for mano inmanos: palos =[]for carta inmano: palos.append(carta[0]) contador_palos =dict(collections.Counter(palos))print(contador_palos)for key,val in contador_palos.items():if val >=5: corrida +=1break probabilidad_corrida = corrida/intentos
print(f'La probabilidad de obtener una corrida en una mano de {tamano_mano} barajas es {probabilidad_corrida}
Solución al reto, fue divertido!
import random
import collections
PALOS=['espada','corazon','rombo','trebol']VALORES=['as','2','3','4','5','6','7','8','9','10','jota','reina','rey']def crear_baraja(): barajas =[]for palo inPALOS:for valor_numerico, valor inenumerate(VALORES): barajas.append((palo, valor, valor_numerico+1))return barajas
def obtener_mano(barajas, tamano_mano): mano = random.sample(barajas, tamano_mano)return mano
def main(tamano_mano, intentos): barajas =crear_baraja() manos =[]for _ inrange(intentos): mano =obtener_mano(barajas, tamano_mano) manos.append(mano) escaleras =0for mano inmanos: valores =[] valores_numericos =[]for carta inmano: valores.append(carta[1]) valores_numericos.append(carta[2])
# ordenamos las cartas por su valor numérico
valores_numericos.sort() valor_repetido =False # vamos a comprobar si hay alguna carta repetida(en ese caso ya no tendríamos una escalera) counter =dict(collections.Counter(valores))for val in counter.values():if val >1: valor_repetido =Truebreakif not valor_repetido: # si la última carta tiene el valor equivalente a la primera carta más el tamaño-1(para saber que valor de la carta debería ser la última), se cuenta como escalera
if valores_numericos[len(valores_numericos)-1]==(valores_numericos[0]+(tamano_mano-1)): escaleras +=1print(valores)print(valores_numericos) probabilidad_escalera = escaleras / intentos
print(f'La probabilidad de obtener un par en una mano de {tamano_mano} barajas es {probabilidad_escalera}')if __name__ =='__main__': tamano_mano =int(input('De cuantas cartas sera la mano: ')) intentos =int(input('Cuantos intentos para calcular la probabilidad: '))main(tamano_mano, intentos)
if valores_numericos[len(valores_numericos)-1] ==(valores_numericos[0] + (tamano_mano-1)):
escaleras += 1
no comprendo bien como sabes si es una escalera con esta linea, me explicas?
uff genial gracias por compartir
Resolvi el reto para la probabilidad de una escalera de distintos palos y del mismo palo para cualquier tamaño de la mano menor al numero de valores (13):
import random
import collections
PALOS=['espada','corazon','rombo','trebol']VALORES=['A','2','3','4','5','6','7','8','9','10','J','Q','K']def crear_baraja(): barajas =[]for palo inPALOS:for valor inVALORES: barajas.append((palo, valor))return barajas
def obtener_mano(barajas, tamano_mano): mano = random.sample(barajas, tamano_mano)return mano
def obtener_valores(mano): valores_mano =[]for carta inmano: valores_mano.append(carta[1])return valores_mano
def ordenar_mano(valores_mano): mano_ordenada =[]forVALORinVALORES:for valor invalores_mano:ifVALOR== valor: mano_ordenada.append(valor)return mano_ordenada
def arreglos_escalera(mano_ordenada): arreglos =[] n_arreglos =len(VALORES)-len(mano_ordenada)+1for i inrange(0, n_arreglos): arreglos.append(VALORES[i: i + tamano_mano])return arreglos
def es_escalera(arreglos, mano_ordenada): acum =0for arreglo inarreglos:if mano_ordenada == arreglo: acum +=1if acum >0:returnTrueelse:returnFalsedef es_escalera_mismo_palo(arreglos, mano_ordenada, mano): palos =[] hay_color =Falsefor carta inmano: palos.append(carta[0]) counter_palos =dict(collections.Counter(palos))for palo in counter_palos.values():if palo ==len(mano): hay_color =Trueif hay_color ==True: acum =0for arreglo inarreglos:if mano_ordenada == arreglo: acum +=1if acum >0:returnTrueelse:returnFalsedef main(tamano_mano, intentos): barajas =crear_baraja() cantidad_escaleras =0 cantidad_escaleras_mismo_palo =0for _ inrange(intentos): mano =obtener_mano(barajas, tamano_mano) valores_mano =obtener_valores(mano) mano_ordenada =ordenar_mano(valores_mano) arreglos_posibles =arreglos_escalera(mano_ordenada) hay_escalera =es_escalera(arreglos_posibles, mano_ordenada)if hay_escalera ==True: cantidad_escaleras +=1 hay_escalera_mismo_palo =es_escalera_mismo_palo(arreglos_posibles, mano_ordenada, mano)if hay_escalera_mismo_palo ==True: cantidad_escaleras_mismo_palo +=1 probabilidad_escalera = cantidad_escaleras / intentos
print(f'La probabilidad de encontrar una escalera en {intentos} intentos es {probabilidad_escalera}') probabilidad_escalera_mismo_palo = cantidad_escaleras_mismo_palo / intentos
print(f'La probabilidad de encontrar una escalera del mismo palo en {intentos} intentos es {probabilidad_escalera_mismo_palo}')if __name__ =="__main__": tamano_mano =int(input('De cuantas barajas sera la mano: ')) intentos =int(input('Cuantos intentos para calcular la probabilidad: '))main(tamano_mano, intentos)```
exelente.....comprendi mejor con tu codigo.....
Hola
Donde ordenas la mano?
es decir, a simple vista se ve que es en def ordenar_mano
pero no veo como 3 for loops pueden ordenar a una mano.
Gracias
Hola, quiero saber si alguien me puede ayudar a hacer un algortimo. hasta ahora lo que he aprendido no me ha dado para hacerlo, es los siguiente:
No se si estoy erroneo pero a mi forma de ver no es un problema netamente estocastico o probabilistico por que no logro observar las variables aleatorias, parece mas un problema de condicionales.
Pero esperar cualquier otra opinion de la comunidad.
Hola
Te recomuendo el punto de:
En cuento a tu problema, me parece que faltaria el set de datos, lo tienes? (cuantos son de cada edad, de cada estrato y demás)
Suena a un problema interesante, con el curso que te sugieros y la base de datos, puedes hacer un análisis.
Desde el punto de la estocastica.... puede que puedas simular el problema.. y depronto generar los datos... pero no tendria claro como, sin embargo si ya tienes los datos seria más un trabajo de análitica.
¿que es una corrida?
Hola 👋🏼
Corrida es otra forma de llamar a la Escalera en una mano de poker.
La corrida/escalera es cuando tus cartas aumentan de valor consecutivamente, 2, 3, 4, 5, 6.
a okey es que solo conocía el nombre de escalera
una consulta la semantica de " val == 2: "? que significa no la he visto en ninguna clase hasta ahora
Hola, Kevin. 👋
El == sirve para hacer una comparación entre dos elementos. Al final, regresa true o false.
Por ejemplo:
a =3if a ==1:print("a es igual a 1")elseif a ==2:print("a es igual a 2")elseif a ==3:print("a es igual a 3")
Al final, se imprimirá a es igual a 3.
Traté de sacar varias jugadas, la menos probable puede dar 0 en un millón de intentos, por lo que creo que la comparación del orden puede fallar en algún aspecto; agradecería comentarios.
En cuanto avance un poco más trataré de regresar para resolverlo.
import random
import collections
PALOS=['espada','corazon','rombo','trebol'] #ConstantesVALORES=['as','2','3','4','5','6','7','8','9','10','jota','reina','rey']ESCALERA_REAL=['as','10','jota','reina','rey']def crear_baraja(): barajas =[]for palo inPALOS:for valor inVALORES: barajas.append((palo, valor))return barajas
def obtener_mano(barajas, tamano_mano): mano = random.sample(barajas, tamano_mano)return mano
def main(tamano_mano, intentos): barajas =crear_baraja() manos =[]for _ inrange(intentos): mano =obtener_mano(barajas, tamano_mano) manos.append(mano) doble_par =0 pares =0 escalera =0 fullhouse =0 poquer =0 escalera_color =0 flor =0 trio =0for mano inmanos: valores =[] palo =[]for carta inmano: valores.append(carta[1]) #Se obtiene indice 1, arreglo inicial barajas, tamano_mano o 1,2 counter =dict(collections.Counter(valores))for val in counter.values():if val ==2: pares +=1 elif val ==3: trio +=1 elif val ==4: poquer +=1for palos inmano: palo.append(palos[0]) counter_palo =dict(collections.Counter(palo))for val_palo in counter_palo.values():if val_palo ==5 and [set(valores)==set(ESCALERA_REAL)&set(valores) and set(ESCALERA_REAL)==set(ESCALERA_REAL)&set(valores)]==True: flor +=1 elif val_palo ==5: fullhouse +=1 elif val_palo ==2 and val_palo ==2: doble_par +=1break probabilidad_doble_par = doble_par / intentos
probabilidad_par = pares / intentos
probabilidad_trio = trio / intentos
probabilidad_fullhouse = fullhouse / intentos
probabilidad_poquer = poquer / intentos
print(f'La probabilidad de obtener un doble par en una mano de {tamano_mano} barajas es {probabilidad_doble_par}'print(f'La probabilidad de obtener un par en una mano de {tamano_mano} barajas es {probabilidad_par}')print(f'La probabilidad de obtener un trio en una mano de {tamano_mano} barajas es {probabilidad_trio}')print(f'La probabilidad de obtener un fullhouse en una mano de {tamano_mano} barajas es {probabilidad_fullhouse}')print(f'La probabilidad de obtener un poquer en una mano de {tamano_mano} barajas es {probabilidad_poquer}')print(f'La probabilidad de obtener una flor imperia en una mano de {tamano_mano} barajas es {probabilidad_flor}')if __name__ =='__main__': tamano_mano =int(input('De cuantas barajas sera la mano: ')) intentos =int(input('Cuantos intentos para calcular la probabilidad: '))main(tamano_mano, intentos)