No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Simulación de Barajas

17/24
Recursos

¡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.

Aportes 224

Preguntas 26

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Uffff admito que sacar las probabilidades de todas las manos de Poker si me costo algo de trabajo pero aqui estan:

link del codigo -> https://colab.research.google.com/drive/1-iKJGnMU1G_BPn7bswtYLLJh824RQjxq

Saludos!

¡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:

def escalera_color(tamano_mano, intentos):
    # Creamos una baraja de cartas
    cartas = crear_baraja()

    # Creamos tantas manos como nos indicó el usuario
    manos = []
    for _ in range(intentos):
        mano = obtener_mano(cartas, tamano_mano)
        manos.append(mano)

    escaleras = 0
    for 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)
        if len(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 color
                if 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 consecutivos
            for i, valor in enumerate(valores):
                if i != 0:
                    if valor - valores[i-1] != 1:
                        es_escalera = False
                        break

            # Si todo se cumplió, sumamos uno al contador de escaleras
            if es_escalera:
                escaleras += 1

    print(f'Escaleras: {escaleras}')
    probabilidad_de_encontrar_escalera = (escaleras / intentos) * 100
    print(
        f'La probabilidad de encontrar una escalera de color en una mano de {tamano_mano} cartas es de {probabilidad_de_encontrar_escalera}%')

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 in PINTA:
        for valor in VALOR:
            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 _ in range(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=0

    for mano in manos:
        valores=[]
        pintas=[]
        for carta in mano:
            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
            if len(minando_escalera)==5:
                    if (abs(minando_escalera[0]-minando_escalera[4])==4):
                        esc=True
                        
                    if (minando_escalera[0]==1):
                        if (minando_escalera[1]==10)&(abs(minando_escalera[1]-minando_escalera[4])==3):
                            escr=True
                            
            
            return esc,escr

  
        def color_funcion(counter_pintas):
            # Identificando si hay Color
            cr=False
            if len(counter_pintas)==1:
                cr=True
            return cr


        def valor_pareja(counter):
            # Funcion que Clasifica Los Valores par, doble par, Trio, Poker y Full 		 
                                House
            c=False
            dob_par=False
            par=False
            pok=False
            tr=False
            fh=False

            for val in counter.values():
                # Clasificando Poker
                if val==4:
                    pok=True
                # Clasificando Trio
                if val==3:
                    tr=True
                # Clasificando Doble Par
                if (val==2)&(c==True):
                    dob_par=True
                # Clasificando Par
                if (val==2)&(c==False):
                    par=True
                    c=True
                # Clasificando Full House
                if (tr==True)&(c==True):
                    fh=True
                   
            

            return  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

        # Indentificando Escalera Real
        if (contador_escaleras[1]==True)&(contado_color==True):
            escalera_real+=1
            print(f"Aparecio la mano Milagrosa {mano}")
        
        if (contador_escaleras[0]==True)&(contado_color==True):
            escalera_color+=1
            print(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 in range(len(probabilidades)):
        print(f"Probabilidad de {j[i]}: {probabilidades[i]/intentos}")```

Aqui está el reto 😄!! Me gustó hacerlo e incluso apliqué sort merge para ordenar la lista y comparar de forma más eficaz 😄!

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 in PALOS:
        for valor in VALORES:
            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 _ in range(intentos):
        mano = obtener_mano(barajas,tamaño_mano)
        manos.append(mano)

    pares = 0

    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        counter = dict(collections.Counter(valores))
        for val in counter.values():
            if val==2:
                pares +=1
                break
    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 _ in range(intentos):
        mano_corrida = obtener_mano(barajas_2,tamaño_mano_corrida)
        manos.append(mano_corrida)
    
    corridas=0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        contador = dict(collections.Counter(valores))
        valores_sorted=sort_merge(valores)
        i=0
        while((valores_sorted[i]-valores_sorted[i+1])==-1):
            i+=1
            if i==len(valores_sorted)-1:
                corridas+=1
                break
        
    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):
    if len(lista)>1:
        #Dividing these lists until we get every list with 1 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
        #Iterators for the main list
        k=0
        while len(left_list)>i and len(right_list)>j:
            if left_list[i]>right_list[j]:
                lista[k]=right_list[j]
                j+=1
            else:
                lista[k]=left_list[i]
                i+=1
            k+=1
        while len(left_list)>i:
            lista[k] = right_list[i]
            i+=1
            i += 1
            k += 1
        while len(right_list)>j:
            lista[k]=right_list[j]
            j+=1
            k+=1

        return 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)
 

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

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

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 _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    pares = 0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])

        for val in valores:
            if int(valores[4])-int(valores[0]) == 4 and (int(valores[0])+int(valores[1])+int(valores[2])+int(valores[3])+int(valores[4]))%5 == 0:
                pares += 1
                break


    probabilidad_par = pares / intentos
    print(f'La probabilidad de obtener una en una mano de {tamano_mano} barajas es {probabilidad_par}')

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 in PALOS:
        for valor in VALORES:
            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 = 0
    for mano in manos:
        valores = []

        # Obtener valor numerico de cada carta
        for carta in mano:
            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:
                break
            else:
                anterior = copy.copy(valor)
        
        # Contar si es corrida
        if esCorrida:
            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 _ in range(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)

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 in range(1,14)]


def create_deck():
    decks = []
    for deck in SUITS:
        for value in VALUES:
            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 new list created as a range with the min and max value"""
    return sorted(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 _ in range(attemps):
        hand = get_hand(decks, hand_size)
        hands.append(hand)

    #Loop over the hands to find the probabilities
    for hand in hands:
        values = []
        suits = []

        for card in hand:
            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, TWO PAIR, TRIPS and POKER
        for val in counter_values.values():
            if val == 2:
                if pair_flag:
                    two_pairs += 1
                else:
                    pairs += 1
                    pair_flag = True
            if val == 3:
                trio += 1
                trio_flag = True
            if val == 4:
                poker += 1

        #FLUSH
        for val in counter_suits.values():
            if val == hand_size:
                flush += 1
                flush_flag = True
                break
        
        #FULL HOUSE: We need a pair and a Three of a kind
        if pair_flag and trio_flag:
            full_house += 1

        #STRAIGHT: Consecutives values
        if is_straight(values):
            straight += 1
            straight_flag = True
        
        #STRAIGHT FLUSH: Straight + Flush
        if straight_flag and flush_flag:
            straight_flush += 1

    print(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=0
    if tamano_mano < 5:
        print('la probabilidad de obtener una corrida es 0')
    else:
        for mano in manos:
            palos = []
            for carta in mano:
                palos.append(carta[0])
            
            contador_palos = dict(collections.Counter(palos))
            print(contador_palos)
            for key,val in contador_palos.items():
                if val >= 5 : 
                    corrida += 1
                    break
                    
    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 in PALOS:
        for valor_numerico, valor in enumerate(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 _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    escaleras = 0
    for mano in manos:
        valores = []
        valores_numericos = []
        for carta in mano:
            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 = True
                break

        if 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 += 1
                print(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)

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 in PALOS:
        for valor in VALORES:
            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 in mano:
        valores_mano.append(carta[1])
    return valores_mano

def ordenar_mano(valores_mano):
    mano_ordenada = []
    for VALOR in VALORES:
        for valor in valores_mano:
            if VALOR == valor:
                mano_ordenada.append(valor)
    return mano_ordenada

def arreglos_escalera(mano_ordenada):
    arreglos = []
    n_arreglos = len(VALORES) - len(mano_ordenada) + 1
    for i in range(0, n_arreglos):
        arreglos.append(VALORES[i: i + tamano_mano])
    return arreglos

def es_escalera(arreglos, mano_ordenada):
    acum = 0
    for arreglo in arreglos:
        if mano_ordenada == arreglo:
            acum += 1
    if acum > 0:
        return True
    else:
        return False

def es_escalera_mismo_palo(arreglos, mano_ordenada, mano):
    palos = []
    hay_color = False
    for carta in mano:
        palos.append(carta[0])
    counter_palos = dict(collections.Counter(palos))
    for palo in counter_palos.values():
        if palo == len(mano):
            hay_color = True
    if hay_color == True:
        acum = 0
        for arreglo in arreglos:
            if mano_ordenada == arreglo:
                acum += 1
        if acum > 0:
            return True
        else:
            return False

        
def main(tamano_mano, intentos):
    
    barajas = crear_baraja()
    cantidad_escaleras = 0
    cantidad_escaleras_mismo_palo = 0
    for _ in range(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)
            ```

Hola, hice la simulación Montecarlo para todos los resultados del Póker de manos de 5 cartas. Lo monté en un tutorial en este curso y mis resultados fueron los siguientes:

Aunque la presentación del tutorial no quedó bien (ayudaría mucho que pudiera hacer drafts y guardar progreso parcial al crear un tutorial). He pedido que lo quiten (tampoco puedo borrarlo) porque quiero subirlo de nuevo de una forma ordenada.

#!/usr/bin/python


from random import sample
from pprint import pprint
from collections import Counter


SUITS = ["sword", "heart", "clovers", "diamonds"]
VALUES= ["as", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]


def create_deck() -> list:
    return [(suit, value) for suit in SUITS for value in VALUES]


def start_hand(decks: list, size_hand: int):
    return sample(decks, size_hand)


def main(size_hand: int, attempts: int):

    hands = list()
    for _ in range(attempts):
        hands.append(start_hand(create_deck(), size_hand))
    
    pairs = 0
    counter = 0
    for hand in hands:
        values = list()
        for cart in hand:
            values.append(cart[1])

        counter = dict(Counter(values))

        for val in counter.values():
            if val == 2:
                pairs += 1
                break
    probability = pairs / attempts
    print(f"Probability of found in a size of hand {size_hand} decks is {probability}")

if __name__ == "__main__":

    size_hand = int(input("Which size of hand do you want to start?> "))
    attempts = int(input("Number of attempts?> "))
    
    main(size_hand, attempts)

Algo que no me quedo claro y lo investigue un poco:
collections.Counter, lo que hace es contar los elementos repetidos en una lista y retorna un diccionario tomando como llave el valor de la lista y como valor la cantidad de veces que se repite, en la documentación del modulo collections los ejemplos que hay no se hacen con diccionarios (aunque Counter devuelva uno), así que para probar quite el “dict” y funciono exactamente igual que con el dict, asi que asumo que se puede presidir de esa declaración, si alguien sabe porque lo puso el profe asi seria chevere si me puede explicar. les dejo el link de la documentación por si quieren investigar un poco mas algunas de las otras clases que tiene este modulo:

namedtuple() factory function for creating tuple subclasses with named fields
deque list-like container with fast appends and pops on either end
Counter dict subclass for counting hashable objects
OrderedDict dict subclass that remembers the order entries were added
defaultdict dict subclass that calls a factory function to supply missing values
UserDict wrapper around dictionary objects for easier dict subclassing
UserList wrapper around list objects for easier list subclassing
UserString wrapper around string objects for easier string subclassing

https://docs.python.org/3.1/library/collections.html

Cumpliendo con el reto 😃


.
El tema del póquer es nuevo para mi, así que inicio definiendo una corrida (lo que encontré en Wikipedia).
El color (flush) o también llamado “corrida” es una combinación de cinco cartas del mismo palo (o más), no necesariamente consecutivas.
.
Como podrán intuir solo cambia la función main()

def main(tamano_mano, intentos):
    barajas = crear_baraja()
    manos = []
    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    corrida = 0
    for mano in manos:
        tipo_palo = []
        for carta in mano:
            tipo_palo.append(carta[0])
        
        counter = dict(collections.Counter(tipo_palo)) 
        #print(counter)
        for val in counter.values():
            if val == 5:
                corrida += 1
                break

    probabilidad_corrida = corrida / intentos
    print(f'La probabilidad de obtner una corrida en una mano de {tamano_mano} barajas es {probabilidad_corrida}')

La probabilidad es de 0.001938, 0.001986 y 0.001994; en 3 simulaciones de 1000000

Realice algo similar pero con el juego de domino para saber las mulas en una jugada.

De cuantas barajas será la mano? 7
De cuantas intentos para calc la probabilidad? 1000
La probabilidad de obtener un par en una mano de 7 barajas es 0.76

Lo interesante fue al coger una baraja completa y emular el ejercicio, y comprobar q efectivamente casi todas las veces salia al menos un par

No se que es una corrida, no juego mucho al poker lo siento jajaja pero intente buscar la Royal Flush o algo asi y este fue mi codigo

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 in PALOS:
        for valor in VALORES:
            barajas.append((palo,valor))

    return barajas

def obtener_una_mano(barajas, tamaño_mano):
    mano = random.sample(barajas, tamaño_mano)

    return mano

def main(tamaño_mano, intentos):
    barajas = crear_baraja()
    manos = []

    #Crea una mano
    for _ in range(intentos):
        mano = obtener_una_mano(barajas, tamaño_mano)
        manos.append(mano)

    #Secuencia de analisis
    #Inicializamos los contadores
    contador_royal_flush = 0
    contador_valores = 0

    #Recorremos las manos
    for mano in manos:
        valores = []
        palos = []
        #Recorremos las cartas de la mano
        for carta in mano:
            #Añadimos el palo y el valor de la carta a sus respectivas listas
            valores.append(carta[1])
            palos.append(carta[0])
        
        #Añadimos un contador de los palos
        counter_palos = dict(collections.Counter(palos))
        
        #Recorremos el contador en busca de una mano que tenga 5 cartas del mismo palo
        for val in counter_palos.values():
            if val == 5:
                contador_valores = 0
                #Recorremos cada valor de esa mano en busca de las 5 cartas que necesitamos
                for val in valores:
                    #No hay cartas con el mismo palo y mismo valor, con lo cual no hay que corroborar nada
                    if val == "as" or val == "10" or val == "jota" or val == "reina" or val == "rey":
                        contador_valores += 1
                        #Si hay una mano con estas 5 cartas, agregamos 1 al contador 
                        if contador_valores == 5:
                            contador_royal_flush += 1
                            mano_ganadora = mano


    print(f"La mano ganadora es {mano_ganadora}")
    probabilidad_royal_flush = contador_royal_flush / intentos
    print(f"La probabilidad de obtener una corrida imperial en una mano de {tamaño_mano} cartas es de {probabilidad_royal_flush}")


if __name__ == "__main__":
    tamaño_mano = int(input("De cuantas cartas sera la mano: "))
    intentos = int(input("Cuantos intentos para calcular la probabilidad:"))

    main (tamaño_mano, intentos)
def main(tamaño_mano, intentos):
    barajas = crear_baraja()
    manos = []

    for _ in range(intentos):
        mano = obtener_mano(barajas, tamaño_mano)
        manos.append(mano)
    
    pares = 0
    corrida = 0
    
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        
        corrida_list = [value for key, value in valores]
        counter = dict(collections.Counter(valores))
        sort_list = sorted(corrida_list)
        

        for val in counter.values():
            if val == 2:
                pares += 1
                corrida = 0
                break
        
        for index in range(len(sort_list)):
            try:
                if (sort_list[index+1] - sort_list[index]) == 1:
                    corrida +=1
            except IndexError:
                pass

    probabilidad_par = pares / intentos
    probabilidad_corrida = corrida / intentos

    print(f'La probabilidad de encontrar un par en una mano de {tamaño_mano} barajas es {probabilidad_par * 100} %')
    print(f'La probabilidad de encontrar una corrida en una mano de {tamaño_mano} barajas es {probabilidad_corrida * 100} %')

la probabilidad de sacar escalera es de aproximadamente 0.3%

Mi solución:

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 in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    
    return barajas


def obtener_mano(baraja, tamano_mano):
    mano = random.sample(baraja, tamano_mano)

    return mano
  

def escalera_color(manos):
    escaleras = 0
    escaleras_color = 0
    for mano in manos:
        numeros = ordenar_mano(mano)
       
        if numeros[0][1] + 4 == numeros[4][1]:
            escaleras += 1

            palo = numeros[0][0]
            palo_igual = True

            for carta in numeros:
                if carta[0] != palo:
                    palo_igual = False
                    break
            
            if palo_igual:
                escaleras_color += 1

    return (escaleras, escaleras_color)


def ordenar_mano(mano):
    mano_ordenada = []
    for carta in mano:
        if carta[1] == 'as':
            mano_ordenada.append((carta[0], 1))
        elif carta[1] == 'jota':
            mano_ordenada.append((carta[0], 11))
        elif carta[1] == 'reina':
            mano_ordenada.append((carta[0], 12))
        elif carta[1] == 'rey':
            mano_ordenada.append((carta[0], 13))
        else:
            mano_ordenada.append((carta[0], int(carta[1])))

    mano_ordenada.sort(key= lambda tup: tup[1])

    return mano_ordenada


def flor_imperial(manos):
    flores = 0

    for mano in manos:
        mano_ordenada = ordenar_mano(mano)

        if mano_ordenada[0][1] == 1:
            palo = mano_ordenada[0][0]
            palo_igual = True

            for carta in mano_ordenada:
                if carta[0] != palo:
                    palo_igual = False
                    break
            
            if palo_igual:
                if mano_ordenada[1][1] == 10 and mano_ordenada[2][1] == 11 and mano_ordenada[3][1] == 12 and mano_ordenada[4][1] == 13:
                    flores +=1

    return flores
  

def main(tamano_mano, intentos):
    baraja = crear_baraja()

    manos = []

    for _ in range(intentos):
        mano = obtener_mano(baraja, tamano_mano)
        manos.append(mano)

    pares = 0
    pares_dobles = 0
    tercias = 0
    poker = 0
    full = 0

    for mano in  manos:
        valores = []
        pares_d = 0
        tercia_f = 0
        for carta in mano: 
            valores.append(carta[1])
        
        counter = collections.Counter(valores)
        
        for val in counter.values():
            if val == 2:
                pares += 1
                pares_d += 1
            if val == 3:
                tercias += 1
                tercia_f += 1
            if val == 4:
                poker += 1
        if pares_d == 2:
            pares_dobles += 1
            pares -= 1
        if pares_d and tercia_f:
            full += 1
    

    escalera = escalera_color(manos)
    escaleras = escalera[0]
    escaleras_color = escalera[1]
    flor = flor_imperial(manos)

    probabilidad_pares = pares / intentos
    probabilidad_pares_dobles = pares_dobles / intentos
    probabilidad_tercias = tercias / intentos
    probabilidad_poker = poker / intentos
    probabilidad_full = full / intentos
    probabilidad_escalera = escaleras / intentos
    probabilidad_escaleras_color = escaleras_color / intentos
    probabilidad_flor = flor / intentos
            
    print(f'Pobabilidad pares = {probabilidad_pares * 100}%')
    print(f'Pobabilidad pares dobles = {probabilidad_pares_dobles * 100}%')
    print(f'Pobabilidad tercias = {probabilidad_tercias * 100}%')
    print(f'Pobabilidad poker = {probabilidad_poker * 100}%')
    print(f'Pobabilidad escalera = {probabilidad_escalera * 100}%')
    print(f'Pobabilidad full = {probabilidad_full * 100}%')
    print(f'Pobabilidad Escalera de Color = {probabilidad_escaleras_color * 100}%')
    print(f'Pobabilidad Flor Imperial = {probabilidad_flor * 100}%')
    
    
    

if __name__ == "__main__":
    tamano_mano = 5
    intentos = 1000000
    main(tamano_mano, intentos)```

import random
import collections

PALOS=[‘espada’,‘diamantes’, ‘corazon’, ‘trebol’]
VALORES=[‘as’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’,‘10’,‘jota’,‘reina’,‘rey’] #Mayuscula por que es ina constante en Python

def crear_baraja ():
barajas=[]
for palo in PALOS:
for valor in VALORES:
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 _ in range(intentos):
    mano=obtener_mano(barajas, tamano_mano)
    manos.append(mano)

i=0
pares=0
terna=0
escalera=0
for mano in manos:
    valores=[]
    
    for carta in mano:
        valores.append(carta[1])
    counter=dict(collections.Counter(valores))   #se pone con mayuscula por que es una clase
        #print (counter)
    for val in counter.values(): #como ahora es un diccionarios se puede acceder a estos directamente con values
        if val==2:
            pares +=1
            break
            
        if val==3:
            terna+=1 
            break
        
        #if val==1 and valores[0]<valores[1]<valores[2]<valores[3]<valores[4] :
            #escalera+=1
            #break
            
        if val==1:
            if valores[0]<valores[1]:
                if valores[1]<valores[2]:
                    if valores[2]<valores[3]:
                        if valores[3]<valores[4]:
                            escalera+=1
                            break
                
            
    #print(valores[::1])    
    #print(counter) 
    
probabilidad_par=pares/intentos
probabilidad_impar=terna/intentos
probabilidad_escalera=escalera/intentos
    
print(f'Probabilidad de tener un par en una mano {tamano_mano} barajas es {probabilidad_par}')
print(f'Probabilidad de tener una terna en una mano {tamano_mano} baraja es {probabilidad_impar}')
print(f'Probabilidad de tener una escalera en una mano {tamano_mano} baraja es {probabilidad_escalera}')

if name==‘main’:
#barajas=crear_baraja()
#print(barajas)
#mano=obtener_mano(barajas, 5)
#print(mano)
tamano_mano=int(input('De cuantas barajas sera la mano: '))
intentos=int(input('Cuantos intentos para calcular la probabilidad: '))

main(tamano_mano, intentos)
import random
import collections

PALOS = ['espada', 'corazon', 'diamante', 'trebol']
VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey']

def crear_baraja(): 
    barajas = []

    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))

    return barajas


def obtener_mano(barajas, tamano_mano):
    baraja = random.sample(barajas, tamano_mano)
    return baraja

def crear_corridas(barajas, numero_de_cartas):
    corridas = []

    for palo in PALOS:
        for i in range(0, (len(VALORES) - numero_de_cartas) + 1):
            corrida = []
            for j in range(0, numero_de_cartas):
                corrida.append((palo, VALORES[i+j]))

            corridas.append(corrida)

    return corridas


def main(tamano_mano, intentos):
    barajas = crear_baraja()
    corridas = crear_corridas(barajas, tamano_mano)

    manos = []

    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    repeticiones = 0
    for mano in manos:
        for corrida in corridas:
            if all(i in corrida for i in mano):
                repeticiones += 1
        
    probabilidad = repeticiones / intentos
    print(f'La probabilidad de obtener una corrida en una mano de {tamano_mano} es {probabilidad}')

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)

Nota de cornell de las clases:

codigo:

# -*- coding: utf-8 -*-
"""
Created on Wed Jun  3 12:08:32 2020

@author: Daniel Galvis
"""
import random
import collections

# BEGIN DECK
def create_deck(sticks,value):
    list_combination=[]
    for i in sticks:
        for j in values:
            list_combination.append((i,j))
    return list_combination

def get_hand(deck,hand_size):
    hand=random.sample(deck,hand_size)
    return hand

def main(hand_size,attempts,sticks,values):
    list_combination=create_deck(sticks,values)
    hands=[]
    for i in range(attempts):
        hands.append(get_hand(list_combination,hand_size))
    return hands

#FLUSH FUNCTIONS
def flush(hands,hand_size):
    quantity=0
    value=[]
    for i in hands:
        for j in range(hand_size):
            value.append(i[j][0])
        counter = dict(collections.Counter(value))
        for val in counter.values():
            if val== 5:
                quantity+=1
        value=[]
    return quantity

# STAIRS FUNCTIONS
def buscar(objective_value,cards):
    for i in cards:
        if objective_value==i:
            return 1
        else:
            return 0
        
def adjustment(num,objective):
    if num >= objective:
        return True
    else:
        return False

def check_stairs(hand,hand_size,lista):
    counter=0
    for j in range(hand_size):    
            if hand[j][1] in lista:
                counter+=1
                lista.remove(hand[j][1])
    return counter

def redifined():
    lista1=['A','2','3','4','5']
    lista2=['2','3','4','5','6']
    lista3=['3','4','5','6','7']
    lista4=['4','5','6','7','8']
    lista5=['5','6','7','8','9']
    lista6=['6','7','8','9','10']
    lista7=['7','8','9','10','J']
    lista8=['8','9','10','J','Q']
    lista9=['9','10','J','Q','K']
    lista10=['10','J','Q','K','A']
    lista_total_stair=[lista1,lista2,lista3,lista4,lista5,lista6,lista7,lista8,lista9,lista10]
    return lista_total_stair

def stair(hands,hand_size):
    lista_total_stair=redifined()
    quantity=0
    stair=[]
    for hand in hands:
        for lista in lista_total_stair:
            counter=check_stairs(hand,hand_size,lista)
            if adjustment(counter,hand_size)==True:
                quantity+=1
                stair.append(hand)
                break
        lista_total_stair=redifined()
    return quantity

                
if __name__ == '__main__':
    #Inicial Values
    sticks = ['pica','corazon','rombo','trebol']
    values = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
    #__________________
    hand_size=5
    attempts=10000
    hands=main(hand_size,attempts,sticks,values)
    quantity_flush=flush(hands,hand_size)
    quantity_stair=stair(hands,hand_size)```

Probabilidad de obtener una “corrida” = 0.003 en una mano de 5 cartas.

fue dificil pero se consiguio:

import random
import collections

SUITS = ['sword', 'heart', 'rhombus', 'clover']
VALUES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
SPECIAL_CASE = {'as': '1', '10': 'a', 'J': 'b', 'Q': 'c', 'K': 'd'}


def create_deck():
    decks = []
    for deck in SUITS:
        for value in VALUES:
            decks.append((deck, value))

    return decks


def get_hand(decks, hand_length):
    hand = random.sample(decks, hand_length)

    return hand


def main(hand_length, attempts):
    deck = create_deck()

    hands = []
    for _ in range(attempts):
        hand = get_hand(deck, hand_length)
        hands.append(hand)

    straight = 0

    for hand in hands:
        values = []
        for card in hand:
            if SPECIAL_CASE.get(card[1]):
                values.append(SPECIAL_CASE.get(card[1]))
            else:
                values.append(card[1])

        values.sort()

        for idx in range(0, len(values)):
            for i, val in SPECIAL_CASE.items():
                if values[idx] == val:
                    values[idx] = i

        if len(values) == 5:
            if ', '.join(map(str, values)) in ', '.join(map(str, VALUES)):
                straight += 1
        elif len(values) > 5:
            for i in range(0, len(values)):
                if ', '.join(map(str, values)) in ', '.join(map(str, VALUES)):
                    straight += 1

    pair_probability = straight / attempts
    print(
        f'Probability of get a pair in a hand of {hand_length} cards is {pair_probability}')


if __name__ == "__main__":

    hand_length = int(input('What is the length of the hand: '))
    attempts = int(input('How many attempts to calculate the probability: '))

    main(hand_length, attempts)

    decks = create_deck()
    hand = get_hand(decks, 5)

Probabilidad de par: 0.4685
Probabilidad de trio: 0.0222
Probabilidad de corrida: 0.0034

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():
    baraja = []
    for palo in PALOS:
        for valor in VALORES:
            baraja.append((palo, valor))

    return baraja


def obtener_mano(baraja, tamano_mano):
    mano = random.sample(baraja, tamano_mano)
    return mano


def verificar_corrida(values):
    es_corrida = True
    for i in range(len(values) - 1):
        if values[i] != values[i + 1] - 1:
            es_corrida = False

    return es_corrida


def obtener_valor_numerico(val):
    if val == 'as':
        return 1
    elif val == 'jota':
        return 11
    elif val == 'reina':
        return 12
    elif val == 'rey':
        return 13
    else:
        return int(val)


def main(tamano_mano, intentos):
    baraja = crear_baraja()

    manos = []

    for _ in range(intentos):
        mano = obtener_mano(baraja, tamano_mano)
        manos.append(mano)

    pares = 0
    trios = 0
    corridas = 0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])  # Append del valor

        counter = dict(collections.Counter(valores))
        for val in counter.values():
            if val == 2:
                pares += 1
                break;

        for val in counter.values():
            if val == 3:
                trios += 1
                break;

        valores_numericos = []
        for val in valores:
            valores_numericos.append(obtener_valor_numerico(val))

        valores_numericos.sort()

        if verificar_corrida(valores_numericos):
            print(valores)
            print(valores_numericos)
            corridas += 1

    probabilidad_par = pares / intentos
    probabilidad_trio = trios / intentos
    probabilidad_corrida = corridas / intentos
    print(f'Probabilidad de par: {probabilidad_par}')
    print(f'Probabilidad de trio: {probabilidad_trio}')
    print(f'Probabilidad de corrida: {probabilidad_corrida}')


if __name__ == '__main__':
    tamano_mano = int(input('Cual es el tamano de la mano? '))
    intentos = int(input('Cuantos intentos? '))

    main(tamano_mano, intentos)

¡Quiero compartirles mi logro! Fue decepcionante al inicio. Dejé pasar un par de días, y retome. Básicamente opté por calcular la escalera o “corrida” que necesariamente debe tener 5 cartas seguidas, sin importar su palo o figura.

Entonces mi código muestra las 3 probabilidades: la de sacar pares, trio y escalera (corrida).

Opté por “if” anidados para evaluar la secuencia de cartas seguidas una tras de otra. Importé la librería “array” para aplicar el método “sorted” y así poder comparar cada posición de una carta en la eventual escalera.

Este es el código, Podrán ver todas las 1000 manos, y dentro de estas las escaleras respectivas:

import array #Importar métodos y funciones aplicados a arreglos
import random
import collections

PALOS = ['espada', 'corazon', 'rombo', 'trebol']
VALORES = [1,2,3,4,5,6,7,8,9,10,11,12,13]

def crear_carta():
    cartas = []
    for palo in PALOS:
        for valor in VALORES:
            cartas.append((palo, valor))

    return cartas

def obtener_mano(cartas, tamano_mano):
    mano = random.sample(cartas, tamano_mano)

    return mano

def main(tamano_mano, intentos):
    cartas = crear_carta()

    manos = []
    for _ in range(intentos):
        mano = obtener_mano(cartas, tamano_mano)
        manos.append(mano)
    
    pares = 0
    trios = 0
    escaleras = 0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        print(f'Valores {valores}')

        counter = dict(collections.Counter(valores))
        valores_ord = sorted(valores) 
        
        for val1 in counter.values():
            if val1 == 2:
                pares +=1
                break
        for val2 in counter.values():
            if val2 == 3:
                trios +=1
                break
        for i in range(4):
            if valores_ord[i] + 1 == valores_ord[i+1]:
                if i < len(mano):
                    i += 1
                    if i == len(mano)-1:
                        escaleras += 1
                        print(f'La escalera #{escaleras} es {valores_ord}')
            else:
                break
                
    probabilidad_par = pares / intentos
    probabilidad_trio = trios / intentos
    probabilidad_escalera = escaleras / intentos
    print(f'La prob. de tener UN PAR en una mano de {tamano_mano} cartas es de {probabilidad_par}')
    print(f'La prob. de tener UN TRIO en una mano de {tamano_mano} cartas es de {probabilidad_trio}')
    print(f'La prob. de tener UNA ESCALERA DE 5 CARTAS en una mano de {tamano_mano} cartas es de {probabilidad_escalera}')

if __name__ == '__main__':
    tamano_mano = int(input('De cuantas cartas será la mano: '))
    intentos = int(input('Cuantos intentos para calcular la probabilidad: '))

    main(tamano_mano, intentos)
  • Cartas de una mano: 5
  • Simulaciones: 1000000
  • 3564 escaleras simples en 1000000 simulaciones: P=0.003564
  • 19 escaleras de color en 1000000 simulaciones: P=1.9e-05
  • Probabilidad de cualquier escalera = 0.003583
import random

def escalera(mano, cartas_por_mano):
    figuras = [carta[0] for carta in mano]
    figura_a_numerico = { '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, 
        '8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14 }
    numericos_de_figuras = ([figura_a_numerico[figura] for figura in figuras])
    minv = min(numericos_de_figuras)
    numericos_de_figuras_minimizado = [v - minv for v in numericos_de_figuras]
    return set(numericos_de_figuras_minimizado) == set(range(cartas_por_mano))

def mismo_palo(mano):
    palos = set([carta[1] for carta in mano])
    return len(palos) == 1

if __name__ == "__main__":
    cartas_por_mano = int(input('- Cartas de una mano [5]: ') or '5') 
    simulaciones = int(input('- Simulaciones [10]: ') or '10')

    VALORES = '23456789TJQKA'  # T = Ten (minitrampa)
    PALOS = '♠♥♦♣' # 'SHDC'  # Spades Hearts Diamonds Clubs
    mazo = [(v, p) for p in PALOS for v in VALORES]

    escaleras = {"simples": 0, "de_color": 0} 
    for _ in range(simulaciones):
        mano = random.sample(mazo, cartas_por_mano)
        if escalera(mano, cartas_por_mano):
            if mismo_palo(mano):
                escaleras["de_color"] += 1
            else:
                escaleras["simples"] += 1

    print(f'- {escaleras["simples"]} escaleras simples en {simulaciones} simulaciones: P={ escaleras["simples"] / simulaciones}')
    print(f'- {escaleras["de_color"]} escaleras de color en {simulaciones} simulaciones: P={ escaleras["de_color"] / simulaciones}')
    print(f'- Probabilidad de cualquier escalera = {(escaleras["simples"]+escaleras["de_color"]) / simulaciones}')

Hola,

Les comparto mi solución:

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 in PALOS:
        for valor in VALORES:
            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 _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    escaleras = 0

    for mano in manos:
        valores = []
        posiciones = []
        for carta in mano:
            valores.append(carta[1])
            posiciones.append(VALORES.index(carta[1]))

        counter = dict(collections.Counter(valores))
        pos_dif = max(posiciones) - min(posiciones)

        if max(counter.values()) == 1 and pos_dif == 4:
            escaleras += 1
        elif max(counter.values()) == 1 and posiciones == [0, 9, 10, 11 ,12]:
            escaleras += 1

    probabilidad_escalera = escaleras / intentos
    print(f'La probabilidad de obtener una escalera en una mano de {tamano_mano} barajas es {probabilidad_escalera}')

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)

Para resolver el problema, lo comparo con las posiciones de los valores de las cartas, la constante VALORES se encuentra ordenada de forma ascendente lo que permite comparar y se toma el caso especial de [ ‘as’ , ‘10’, ‘jota’, ‘reina’, ‘rey’].

Se logro calcular todas as posibilidades

import random
import collections
import time
import operator

PALOS =['picas', 'corazon', 'diamante', 'trebol']
VALORES = ['As', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jota', 'Reina', 'Rey']


def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))

    return barajas

def obteber_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)
    return mano

def main(tamano_mano, intentos):
    barajas =crear_baraja()

    manos = []
    for _ in range(intentos):
        mano = obteber_mano(barajas, tamano_mano)
        manos.append(mano)
    #Variables para las estadisticas
    pares = 0
    dobles_pares = 0
    trios = 0
    poker = 0
    full = 0
    color = 0
    escalera_pintas = 0
    escalera_color = 0
    escalera_real =  0
    for mano in manos:
        valores = []
        pinta = []
        escalera =[]
        for carta in mano:#Creo los arreglos
            valores.append(carta[1])
            escalera.append(carta[1])
            pinta.append(carta[0])

        for i, escalon in enumerate(escalera):#reemplazo para poder organizar las cartas 
            if escalon == 'As':
                escalera[i] = 1
            elif escalon == 'Jota':
                escalera[i] = 11
            elif escalon == 'Reina':
                escalera[i] = 12
            elif escalon == 'Rey':
                escalera[i] = 13
            else:
                escalera[i] = int(escalon)

        escalera = sorted(escalera)
        posible_escalera = False
        posible_escalera_color = False
        posible_escalera_real = False

        counter = dict(collections.Counter(valores))
        counter_pinta = dict(collections.Counter(pinta))

        if len(counter) >= 5:#Verifico que haya 5 cartas diferentes
            # print('Empieza')
            as_c = False
            diez_c = False
            jota_c = False
            reina_c = False
            rey_c = False
            for escalon in range(len(escalera)-1):

                if escalera[escalon +1] != escalera[escalon] :
                    if escalera[0] == 1 and escalera[1] == 10: # Sew verifica si el primer numero es 1 (As) y el segundoe s 10
                        posible_escalera_real = True
                    elif  escalera[escalon +1] - escalera[escalon]  !=  1: #No son consecutivos
                        posible_escalera = False
                        posible_escalera_color = False
                        posible_escalera_real = False
                        break
                    else: #Son Consecutivos
                        posible_escalera = True
                        posible_escalera_color= True
                        if len(counter) > 5: #Para calcular la flor en manos mayores a 5 cartas
                            # print(escalera[escalon])
                            if escalera[escalon]  == 1:
                                as_c = True
                            elif escalera[escalon]  == 10:
                                diez_c = True
                            elif escalera[escalon]  == 11:
                                jota_c = True
                            elif escalera[escalon]  == 12:
                                reina_c = True
                            if escalera[escalon+1]  == 13:
                                rey_c = True
                if  as_c == True  and diez_c == True and jota_c == True and reina_c == True and rey_c == True:
                    posible_escalera_real = True

        revisa_par = 1
        for val_pinta in counter_pinta.values():
            if val_pinta >= 5: #revisar si es color
                color += 1
                revisa_par = 0
                if posible_escalera_real == True:#Escalera Real
                    escalera_real += 1
                    color -= 1
                    posible_escalera = False
                    print(f'Real: {mano}')
                elif posible_escalera_color == True: #Escalera Color
                    escalera_color +=1
                    posible_escalera = False
                    color -= 1
                    # print(f'Color: {mano}')
                break

        if  posible_escalera == True:
            escalera_pintas += 1
            revisa_par = 0
            # print('Escalera')
            # print(escalera)

        if revisa_par == 1:
            trio_full = False
            par_full = False
            doble_par = 0
            for  val in counter.values():
                if val == 4:
                    poker += 1
                    # print(f'Poker : {counter}')
                    break
                if val == 3:
                    trios += 1
                    trio_full = True
                if val == 2:
                    doble_par  += 1
                    pares += 1
                    par_full = True
                    if doble_par == 2:
                        dobles_pares += 1
                        pares -= 1
                        # print(f'Doble Par : {counter}')

            if par_full == True and trio_full == True:
                full += 1
                pares -= 1
                trios -= 1
                # print(f'Full : {counter}')

    probabilidad_par = pares  / intentos
    probabilidad_doble_par = dobles_pares  / intentos
    probabilidad_trios =  trios / intentos
    probabilidad_color =  color / intentos
    probabilidad_full =  full / intentos
    probabilidad_poker =  poker / intentos
    probabilidad_escalera_real =  escalera_real / intentos
    probabilidad_escalera_color =  escalera_color / intentos
    probabilidad_escalera_pinta =  escalera_pintas / intentos
    print('*-*-' * 50)
    print(f'La probabilidad de obtener una Escalera Real en una mano de {tamano_mano} cartas es: {probabilidad_escalera_real}')
    print(f'La probabilidad de obtener una Escalera Color en una mano de {tamano_mano} cartas es: {probabilidad_escalera_color}')
    print(f'La probabilidad de obtener un Poker en una mano de {tamano_mano} cartas es: {probabilidad_poker}')
    print(f'La probabilidad de obtener un Full en una mano de {tamano_mano} cartas es: {probabilidad_full}')
    print(f'La probabilidad de obtener un Color en una mano de {tamano_mano} cartas es: {probabilidad_color}')
    print(f'La probabilidad de obtener una Escalera en una mano de {tamano_mano} cartas es: {probabilidad_escalera_pinta}')
    print(f'La probabilidad de obtener un Trio en una mano de {tamano_mano} cartas es: {probabilidad_trios}')
    print(f'La probabilidad de obtener un Doble Par en una mano de {tamano_mano} cartas es: {probabilidad_doble_par}')
    print(f'La probabilidad de obtener un Par en una mano de {tamano_mano} cartas es: {probabilidad_par}')



def run():
    while True:
        print('')
        print('*****SIMULACION DE BARAJAS*****')
        print('')
        tamano_mano = int(input('Cuantas cartas tendra la mano (1-52):  '))
        if tamano_mano < 1 or tamano_mano > 52:
            print('El valor ingresado para el numero de cartas que tiene la mano no esta permitido, vuelvalo a intentar.')
            print('')
            run()
        intentos = int(input('Cuantas simulaciones se ejecutara para calcular  la probabilidad (1 - 10000000):  '))
        if intentos < 1 or intentos > 10000000:
            print('El valor ingresado para el numero de simulaciones  no esta permitido, vuelvalo a intentar.')
            print('')
            run()
        print('')
        print('*-*-' * 50)
        print('')
        print('************RESULTADOS************')
        print('')
        t_inicio =time.time()
        main(tamano_mano, intentos)
        t_fin =time.time()
        t_final = t_fin - t_inicio
        print('')
        print(f'El calculo se demoro {t_final} segundos.')
        print('')

if __name__ == "__main__":
    run()

Este fue el resultado en diez millones de simulaciones con 5 cartas.

La probabilidad de obtener una Escalera Real en una mano de 5 cartas es: 1.7e-06, eso significa que solo 17 veces salio la escalera real en la simulación

esto me parece brillante ahora me voy a poner a simular juegos de casino

Perdonen la pedantería de alguien que está intentando ser jugador profesional de poker, pero en la variante "TExas Holdem" , que es la más generalizada en torneos y cash , ya hay muchos softwares que calculan las probabilidades en el flop, en el turn y en el river. Muchos son gratuitos. Un saludo
```js import random import collections PALOS = ["espadas", "corazon", "rombo", "trebol"] VALORES = ["as", "2", "3", "4", "5", "6", "7", "8", "9", "10", "jota", "reina", "rey"] def crear_baraja(): barajas = [] for palo in PALOS: for valor in VALORES: barajas.append((palo, valor)) return barajas def obtener_mano(barajas, tamaño_mano): mano = random.sample(barajas, tamaño_mano) return mano def main(tamano_mano, intentos): barajas = crear_baraja() manos = [] for _ in range(intentos): mano = obtener_mano(barajas, tamano_mano) manos.append(mano) pares = 0 for mano in manos: valores = [] for carta in mano: valores.append(carta[1]) counter = dict(collections.Counter(valores)) for val in counter.values(): if val == 2: pares += 1 break probabilidad_par = pares / intentos print(f"la probabilidad de obtener un par en una mano de {tamano_mano} baraja es {probabilidad_par}") 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) ```import randomimport collections PALOS = \["espadas", "corazon", "rombo", "trebol"]VALORES = \["as", "2", "3", "4", "5", "6", "7", "8", "9", "10", "jota", "reina", "rey"] def crear\_baraja():    barajas = \[]    for palo in PALOS:        for valor in VALORES:            barajas.append((palo, valor))     return barajas def obtener\_mano(barajas, tamaño\_mano):    mano = random.sample(barajas, tamaño\_mano)     return mano def main(tamano\_mano, intentos):    barajas = crear\_baraja()     manos = \[]    for \_ in range(intentos):        mano = obtener\_mano(barajas, tamano\_mano)        manos.append(mano)     pares = 0     for mano in manos:        valores = \[]        for carta in mano:            valores.append(carta\[1])         counter = dict(collections.Counter(valores))        for val in counter.values():            if val == 2:                pares += 1                break     probabilidad\_par = pares / intentos    print(f"la probabilidad de obtener un par en una mano de {tamano\_mano} baraja es {probabilidad\_par}") 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)
Este es mi código siguiendo la lógica de la clase: ```python import random import numpy as np PALOS = ['espada', 'corazon', 'rombo', 'trebol'] VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'rey', 'reina'] def crear_baraja(): barajas = [] for palo in PALOS: for valor in VALORES: barajas.append((palo, valor)) return barajas def obtener_mano(barajas, tamano_mano): mano = random.sample(barajas, tamano_mano) return mano def corrida(tamano_mano, intentos): """Combinación de cinco cartas consecutivas del mismo palo""" barajas = crear_baraja() manos = [obtener_mano(barajas, tamano_mano) for _ in range(intentos)] corridas = 0 for mano in manos: valores = [y for x,y in mano] valores = [VALORES.index(valor)+1 for valor in valores] valores = sorted(valores) if min(valores) == 1 and max(valores) == 13: valores[0]=14 valores = sorted(valores) escalera = sum(np.diff(valores) ==1)>= 4 if escalera: corridas +=1 probabilidad_corrida = corridas/intentos print(f'La probabilidad de obtener una corrida en una mano de {tamano_mano} es {probabilidad_corrida}.') if __name__ == '__main__': tamano_mano = int(input('De cuantas barajas será la mano: ')) intentos = int(input('Cuantos intentos para calcular la probabilidad: ')) corrida(tamano_mano, intentos) ```import randomimport collectionsimport numpy as np PALOS = \['espada', 'corazon', 'rombo', 'trebol']VALORES = \['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'rey', 'reina'] def crear\_baraja():    barajas = \[]    for palo in PALOS:        for valor in VALORES:            barajas.append((palo, valor))    return barajas def obtener\_mano(barajas, tamano\_mano):    mano = random.sample(barajas, tamano\_mano)        return mano def corrida(tamano\_mano, intentos):    """Combinación de cinco cartas consecutivas del mismo palo"""    barajas = crear\_baraja()        manos = \[obtener\_mano(barajas, tamano\_mano) for \_ in range(intentos)]        corridas = 0    for mano in manos:        valores = \[y for x,y in mano]        valores = \[VALORES.index(valor)+1 for valor in valores]            valores = sorted(valores)         if min(valores) == 1 and max(valores) == 13:             valores\[0]=14        valores = sorted(valores)                escalera = sum(np.diff(valores) ==1)>= 4        if escalera:            corridas +=1    probabilidad\_corrida = corridas/intentos    print(f'La probabilidad de obtener una corrida en una mano de {tamano\_mano} es {probabilidad\_corrida}.')            def main(tamano\_mano, intentos):    barajas = crear\_baraja()     manos = \[]    for \_ in range(intentos):        mano = obtener\_mano(barajas, tamano\_mano)        manos.append(mano)        pares = 0    for mano in manos:        valores = \[]        for carta in mano:            valores.append(carta\[1])                counter = dict(collections.Counter(valores))                for val in counter.values():            if val == 2:                pares += 1                break        probabilidad\_par = pares/intentos    print(f'La probabilidad de obtener un par en una mano de {tamano\_mano} es {probabilidad\_par}') if \_\_name\_\_ == '\_\_main\_\_':    tamano\_mano = int(input('De cuantas barajas será la mano: '))    intentos = int(input('Cuantos intentos para calcular la probabilidad: '))    corrida(tamano\_mano, intentos) Y la probabilidad que me da es de 0.00381: ```txt De cuantas barajas será la mano: 5 Cuantos intentos para calcular la probabilidad: 100000 La probabilidad de obtener una corrida en una mano de 5 es 0.00381. ```No sé si es lo correcto o habrá que correrlo mayor cantidad de veces.
```python import random import collections import numpy as np PALOS = ['espada', 'corazon', 'rombo', 'trebol'] VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'rey', 'reina'] def crear_baraja(): barajas = [] for palo in PALOS: for valor in VALORES: barajas.append((palo, valor)) return barajas def obtener_mano(barajas, tamano_mano): mano = random.sample(barajas, tamano_mano) return mano def corrida(tamano_mano, intentos): """Combinación de cinco cartas consecutivas del mismo palo""" barajas = crear_baraja() manos = [obtener_mano(barajas, tamano_mano) for _ in range(intentos)] corridas = 0 for mano in manos: valores = [y for x,y in mano] valores = [VALORES.index(valor)+1 for valor in valores] valores = sorted(valores) if min(valores) == 1 and max(valores) == 13: valores[0]=14 valores = sorted(valores) escalera = sum(np.diff(valores) ==1)>= 4 if escalera: corridas +=1 probabilidad_corrida = corridas/intentos print(f'La probabilidad de obtener una corrida en una mano de {tamano_mano} es {probabilidad_corrida}.') def main(tamano_mano, intentos): barajas = crear_baraja() manos = [] for _ in range(intentos): mano = obtener_mano(barajas, tamano_mano) manos.append(mano) pares = 0 for mano in manos: valores = [] for carta in mano: valores.append(carta[1]) counter = dict(collections.Counter(valores)) for val in counter.values(): if val == 2: pares += 1 break probabilidad_par = pares/intentos print(f'La probabilidad de obtener un par en una mano de {tamano_mano} es {probabilidad_par}') if __name__ == '__main__': tamano_mano = int(input('De cuantas barajas será la mano: ')) intentos = int(input('Cuantos intentos para calcular la probabilidad: ')) corrida(tamano_mano, intentos) ssdfsf ```
Mi código: ```python import random import collections from collections import Counter, deque PALOS = ['espada', 'corazon', 'rombo', 'trebol'] VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey'] def crear_baraja(): # Creamos una lista vacía para almacenar las cartas cartas = [] # Iteramos sobre los palos y los valores para crear cada carta for palo in PALOS: for valor in VALORES: cartas.append((palo, valor)) return cartas def obtener_mano(cartas, cantidad): # Creamos una lista vacía para almacenar las cartas mano = random.sample(cartas, cantidad) return mano def main(cantidad, intentos): orden_preestablecido = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey', 'as'] #Lista de caras cartas = crear_baraja() #Manos manos = [] for intento in range(intentos): mano = obtener_mano(cartas, cantidad) mano =sort_and_convert(mano) manos.append(mano) corridas = 0 for mano in manos: if subsequence(mano): corridas += 1 probabilidad_corridas = corridas / intentos print(f'La probabilidad de obtener un par en una mano de {cantidad} cartas es {probabilidad_corridas}') def sort_and_convert(mano): orden_preestablecido = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey'] orden_dict = {valor: indice for indice, valor in enumerate(orden_preestablecido)} mano = [carta[1] for carta in mano] mano = set(mano) mano = list(mano) mano = sorted(mano, key=lambda x: orden_dict[x]) if 'as' in mano: mano.append('as') return mano def subsequence(mano: list): if len(mano) < 5: return False Orderedlist = ['as','2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey', 'as'] first_element =mano[0] index = Orderedlist.index(first_element) if mano == Orderedlist[index:index+len(mano)]: return True else: return False if __name__ == '__main__': cantidad = int(input('Cantidad de cartas: ')) intentos = int(input('Intentos: ')) main(cantidad, intentos) ```
Mi código : ```js import random import collections from collections import Counter, deque PALOS = ['espada', 'corazon', 'rombo', 'trebol'] VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey'] def crear_baraja(): # Creamos una lista vacía para almacenar las cartas cartas = [] # Iteramos sobre los palos y los valores para crear cada carta for palo in PALOS: for valor in VALORES: cartas.append((palo, valor)) return cartas def obtener_mano(cartas, cantidad): # Creamos una lista vacía para almacenar las cartas mano = random.sample(cartas, cantidad) return mano def main(cantidad, intentos): orden_preestablecido = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey', 'as'] #Lista de caras cartas = crear_baraja() #Manos manos = [] for intento in range(intentos): mano = obtener_mano(cartas, cantidad) mano =sort_and_convert(mano) manos.append(mano) corridas = 0 for mano in manos: if subsequence(mano): corridas += 1 probabilidad_corridas = corridas / intentos print(f'La probabilidad de obtener un par en una mano de {cantidad} cartas es {probabilidad_corridas}') def sort_and_convert(mano): orden_preestablecido = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey', 'as'] orden_dict = {valor: indice for indice, valor in enumerate(orden_preestablecido)} mano = [carta[1] for carta in mano] mano = set(mano) mano = list(mano) mano = sorted(mano, key=lambda x: orden_dict[x]) return mano def subsequence(mano: list): if len(mano) < 5: return False Orderedlist = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey', 'as'] first_element =mano[0] index = Orderedlist.index(first_element) if mano == Orderedlist[index:index+len(mano)]: return True else: return False if __name__ == '__main__': cantidad = int(input('Cantidad de cartas: ')) intentos = int(input('Intentos: ')) main(cantidad, intentos) ```
No se que es una corrida :(

hay un bug en el programa para un par y es que cuenta una mano con dos pares como una mano con un par

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 in PALOS:
        for valor in VALORES:
            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 _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    cuatro_puntos = 0
    escalera = 0

    for mano in manos:
        valores = []
        for carta in mano:
            if carta[1] == "as":
                valores.append(1)
            elif carta[1] == "jota":
                valores.append(11)
            elif carta[1] == "reina":
                valores.append(12)
            elif carta[1] == "rey":
                valores.append(13)
            else:
                valores.append(int(carta[1]))
        baraja_ordenada = sorted(valores)
        # Esto altera el valor de las listas y las  convierte en none lista_ordenada = valores.sort()
        #print(baraja_ordenada)
        
 
            
        for carta in range(tamano_mano - 1):
            """print(f"len de tamano_mano: {range(tamano_mano - 1)}")
            print("carta", carta)"""
            if baraja_ordenada[carta + 1] - baraja_ordenada[carta] == 1 :
                cuatro_puntos += 1 
            """print(f"Resta: {baraja_ordenada[carta + 1]} - {baraja_ordenada[carta]} = {baraja_ordenada[carta + 1] - baraja_ordenada[carta]}")
            print("Cuatro puntos", cuatro_puntos)"""

            if cuatro_puntos == 4:
                escalera += 1
                cuatro_puntos = 0
            if carta == 3 :
                cuatro_puntos = 0
                """print("cuatro puntos se hace 0", cuatro_puntos)"""
        
          
                
              




         
               

        """counter = dict(collections.Counter(valores))
        print(counter)
        for val in counter.values():
            pass
            if val == 3:
                pares += 1
        
                break"""
    #print("numero de escaleras", escalera)
    probabilidad_escalera = escalera / intentos
    print(f'La probabilidad de obtener una escalera en una mano de {tamano_mano} barajas es {probabilidad_escalera}')


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)
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 in PALOS:
        for valor in VALORES:
            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 _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    cuatro_puntos = 0
    escalera = 0

    for mano in manos:
        valores = []
        for carta in mano:
            if carta[1] == "as":
                valores.append(1)
            elif carta[1] == "jota":
                valores.append(11)
            elif carta[1] == "reina":
                valores.append(12)
            elif carta[1] == "rey":
                valores.append(13)
            else:
                valores.append(int(carta[1]))
        baraja_ordenada = sorted(valores)
        # Esto altera el valor de las listas y las  convierte en none lista_ordenada = valores.sort()
        
        
 
            
        for carta in range(len(baraja_ordenada) - 1):
            if baraja_ordenada[carta + 1] - baraja_ordenada[carta] == 1:
                cuatro_puntos += 1 
                
                if cuatro_puntos == 4:
                    escalera += 1
                    cuatro_puntos = 0


         
               

        """counter = dict(collections.Counter(valores))
        print(counter)
        for val in counter.values():
            pass
            if val == 3:
                pares += 1
        
                break"""

    probabilidad_escalera = escalera / intentos
    print(f'La probabilidad de obtener una escalera en una mano de {tamano_mano} barajas es {probabilidad_escalera}')


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) 

esta es la forma en que resolví también está el código de lo que hicimos en clase

import random
import collections


PALOS = ['trebol', 'corazon', 'pica', 'diamante']
VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', 'j', 'q', 'k']

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    return barajas


def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)

    return mano



def ordenar_mano(mano):

    modelo = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'j', 'q', 'k']

    trebol = []
    picas = []
    diamantes = []
    corazones = []

    for carta in mano:
        if carta[0] == 'trebol':
            trebol.append(carta[1])
        elif carta[0] == 'pica':
            picas.append(carta[1])
        elif carta[0] == 'diamante':
            diamantes.append(carta[1])
        elif carta[0] == 'corazon':
            corazones.append(carta[1])

    # print(f'trebol {trebol}')
    # print(f'picas {picas}')
    # print(f'diamntes {diamantes}')
    # print(f'corazones {corazones}')
    
    trebol_ordenado = sorted(trebol, key=lambda carta: modelo.index(carta))
    picas_ordenadas = sorted(picas, key=lambda carta: modelo.index(carta))
    diamantes_ordenados = sorted(diamantes, key=lambda carta: modelo.index(carta))
    corazones_ordenados = sorted(corazones, key=lambda carta: modelo.index(carta))


    return trebol_ordenado, picas_ordenadas, diamantes_ordenados, corazones_ordenados


def escalera(trebol, picas, diamantes, corazones):
    
    modelo = [('as', 0), ('2', 1), ('3', 2), ('4', 3), ('5', 4), ('6', 5), ('7', 6), ('8', 7), ('9', 8), ('10', 9), ('j', 10), ('q', 11), ('k', 12)]

    escalera = 0
    contador = []

    trebol_contador = []
    picas_contador = []
    diamantes_contador = []
    corazones_contador = []

    for x in trebol:
        for i in modelo:
            if x == i[0]:
                carta = (x, i[1])
                trebol_contador.append(carta)

    for x in picas:
        for i in modelo:
            if x == i[0]:
                carta = (x, i[1])
                picas_contador.append(carta)

    for x in diamantes:
        for i in modelo:
            if x == i[0]:
                carta = (x, i[1])
                diamantes_contador.append(carta)

    for x in corazones:
        for i in modelo:
            if x == i[0]:
                carta = (x, i[1])
                corazones_contador.append(carta)


    for carta in trebol_contador:
        if len(contador) == 0:
            contador.append(carta)
        elif len(contador) >= 1:
            ultima_carta = contador[-1]
            if ultima_carta[1] + ultima_carta[1] + 1 == ultima_carta[1] + carta[1]:
                contador.append(carta)
                if len(contador) == 3:
                    escalera += 1
                    break

            else:
                contador = []
                contador.append(carta)
    contador = []

    for carta in picas_contador:
        if len(contador) == 0:
            contador.append(carta)
        elif len(contador) >= 1:
            ultima_carta = contador[-1]
            if ultima_carta[1] + ultima_carta[1] + 1 == ultima_carta[1] + carta[1]:
                contador.append(carta)
                if len(contador) == 3:
                    escalera += 1
                    break

            else:
                contador = []
                contador.append(carta)
    contador = []

    for carta in diamantes_contador:
        if len(contador) == 0:
            contador.append(carta)
        elif len(contador) >= 1:
            ultima_carta = contador[-1]
            if ultima_carta[1] + ultima_carta[1] + 1 == ultima_carta[1] + carta[1]:
                contador.append(carta)
                if len(contador) == 3:
                    escalera += 1
                    break
            else:
                contador = []
                contador.append(carta)
    contador = []

    for carta in corazones_contador:
        if len(contador) == 0:
            contador.append(carta)
        elif len(contador) >= 1:
            ultima_carta = contador[-1]
            if ultima_carta[1] + ultima_carta[1] + 1 == ultima_carta[1] + carta[1]:
                contador.append(carta)
                if len(contador) == 3:
                    escalera += 1
                    break
            else:
                contador = []
                contador.append(carta)
    contador = []
    return escalera


def main(tamano_mano, intentos):
    barajas = crear_baraja()

    manos = []
    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    pares = 0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        
        counter = dict(collections.Counter(valores))
        for val in counter.values():
            if val == 2:
                pares += 1
                break
    
    probabilidad_de_carta_repetida = pares / intentos
    print(f'la probabilidad de optener un carta repetida en una mano de {tamano_mano} cartas es de {probabilidad_de_carta_repetida}')
    
    escaleras = 0

    for mano in manos:
        trebol, picas, diamantes, corazones = ordenar_mano(mano)
        escaleras_encontradas = escalera(trebol, picas, diamantes, corazones)
        if escaleras_encontradas >= 1:
            escaleras += 1

    probabilidad_de_escalera = escaleras / intentos
    print(f'la probabilidad de encontrar una escalera en una mano de {tamano_mano} es de {probabilidad_de_escalera}') 



if __name__ == '__main__':
    tamano_mano = int(input('de cuantas cartas sera la mano: '))
    intentos = int(input('Cuantos intentos para calular probabilidad: '))

    main(tamano_mano, intentos)

Yo lo implemente con Programación Orientada a Objetos, de hecho es mi primer programa del curso que puedo desarrollar solo. Si lees esto y no te sientes seguro si se puede, lo lograras! 😃

import random 
import os
import collections

os.system('clear')

class Poker:
  def __init__(self):   
    self.Num_cartas = int(input('Cuantas cartas queremos? '))
    self.valor_num = []
    self.valor_palo = []
    self.pares = 0
    self.intentos()
    self.probabilidad()
  
  def generar_baraja(self):
    PALO = ['espadas', 'corazones', 'diamantes', 'trevoles']
    NUMEROS = [1,2,3,4,5,6,7,8,9,10,'J','Q','K']
    baraja = []
    for i in PALO:
      for j in NUMEROS:
        carta = (j,i)
        baraja.append(carta)
    return baraja

  def repartir(self):
    baraja = self.generar_baraja()
    self.mano = random.sample(baraja, self.Num_cartas)
    for elem in self.mano:
      self.valor_num.append(elem[0])
      self.valor_palo.append(elem[1])
    
    return self.mano

  def intentos(self):
    self.intentos = int(input('¿Cuantos intentos queremos relizar? '))
    for intento in range(self.intentos):
      self.repartir()
      self.par()  
      self.valor_num.clear()
     
  
  def par(self):
    self.counter_num = dict(collections.Counter(self.valor_num))
    self.counter_palo = dict(collections.Counter(self.valor_palo))
    for val in self.counter_num.values():
      if val == 2:
        self.pares +=1
        break
    
  def probabilidad(self):
    self.probabilidad_par = self.pares /self.intentos
    print(f'La probabilidad de tener un par en un tamaño de mano de {self.Num_cartas} es de {self.probabilidad_par} en {self.intentos} intentos') 

juego1 = Poker()

Por si acaso
J => Jack => Caballero
Q => Queen => Reina
K => King => Rey
A => Primera o ultima, es un comodin
J seria 11, Q seria 12 y K seria 13, mientras que A seria 1 y 14 para empezar de nuevo el ciclo

Se puso interesante esto

Reto cumplido
Posdata: necesitar correr la simulacion un minino de 10000 veces

import random 
import collections

STICKS = ['❤️ ', '🗡️ ', '💎 ', '🍀 ']
VALUES = ['as', '2', '3', '4', '5', '6', '7', '8',
           '9', '10', '🔫', '👸', '🤴']


def create_deck():
    #first we make a for loop to every values with every stick 
    #just a like a regular deck of cards shortly

    deck = [] # 52 cards :)
    for stick in STICKS:
        for value in VALUES:
            deck.append((stick, value))

    return deck

def get_hand(deck, size_of_hand):
    #the random.sample module dont let the values/sticks duplicate
    #it self, the second parameter means how many times we gonna 
    #throw a new "card"

    hand = random.sample(deck ,size_of_hand )
    return hand


def main(size_of_hand, attempts):
    deck = create_deck()   
    hands = []

    for _ in range(attempts):
        hand = get_hand(deck, size_of_hand)
        hands.append(hand)
 
    corridas = 0 
    for hand in hands:
        valuables =[]
        for card in hand:
            valuables.append(card[0])

        counters = dict(collections.Counter(valuables))
        for val in counters.values():

            #print(counters)
            
            if val == 5:
                corridas += 1
                break
            
    corridas_probability =  corridas / attempts      
    print(f'The probability of obtain a corrida in one hand of {size_of_hand} decks is {corridas_probability*100}%')     

if __name__ == '__main__':
    size_of_hand = int(input('How big do you want the size of the hand: ')) 
    attempts = int(input('How many times run the simulation: '))

    main(size_of_hand, attempts)

    

Como reto personal, hce un programa similar haciendo uso de sets, creo que incluso me ahorro un ciclo for.

Que opinan?

<code> 
from random import sample

def crear_barajas():
    numeros = tuple([i for i in range(2,11)] + ["J", "Q", "K", "A"])
    colores = ("picas","trebol","corazon","diamantes")
    lista_de_cartas = []
    for i in numeros:
        for j in colores:
            lista_de_cartas.append((i,j))
    return lista_de_cartas

def es_par(result, pasadas):

    pares = 0
    for i in range(pasadas):
        x = sample(result,5)
        lista_numeros = [i[0] for i in x]
        set_numeros = set(lista_numeros)
        if len(set_numeros) == len(lista_numeros):
            print("No se encontraron pares en esta baraja")
        elif len(set_numeros) == 4:
            pares += 1
            print("Se hallo un par")
        else:
            pares += 1
            print("Sacaste trio, full house o poker, te lo valemos como par")

    return pares/pasadas



if __name__ == "__main__":
    result = crear_barajas()
    while True:
        try:
            pasadas = int(input("Cuantas veces quieres sacar barajas? "))
            break
        except ValueError:
            print("Solo son validos numeros")
            continue

    porcentaje = es_par(result, pasadas)
    print(porcentaje)

RETO logrado (creo)

import random
import collections

PALOS = ['picas', 'corazon', 'trebol', 'rombo']
VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'sota', 'dama', 'rey']

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            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 _ in range(intentos):
        mano =  obtener_mano(barajas, tamano_mano)
        #print(mano)                            #Imprimir manos
        manos.append(mano)
    
    pares = 0
    tercia = 0
    doble_par = 0
    poquer = 0
    full = 0
    color = 0
    escalera = 0
    escalera_color = 0
    escalera_real = 0
    for mano in manos:
        colores = []
        valores = []
        mano_ord = []
        num_par = 0
        stair = False
        flush = False
        posible_full, traigo_par = 0, 0
        for carta in mano:
            valores.append(carta[1])
        for carta in mano:
            colores.append(carta[0])

        for val in valores:
            mano_ord.append(VALORES.index(val))
        mano_ord.sort()
        for i in range(len(mano_ord)-1):
            if mano_ord[i] == mano_ord[i+1] - 1:
                stair = True
            else:
                stair = False
                break
        if stair == True:
            escalera += 1
            #print("Encontre otro")
            #print(mano)

        counter_color = dict(collections.Counter(colores))
        for val in counter_color.values():
            if val == tamano_mano:
                color += 1
                flush = True
                #print("Encontre otro")
                #print(mano)
                break

        if stair == True and flush == True:
            escalera_color += 1
            #print("Encontre otro")
            #print(mano)

        if mano_ord == [0, 9, 10, 11, 12] and flush == True:
            escalera_real += 1
            #print("Encontre otro")
            #print(mano)

        counter = dict(collections.Counter(valores)) #es clase, empieza con mayúscula
        #print(counter)
        for val in counter.values():
            if val == 2:  #exactamente igual a dos
                pares += 1
                #print("Encontre otro")
                #print(mano)
                break
        for val in counter.values():
            if val == 3:
                tercia += 1
                #print("Encontre otro")
                #print(mano)
                break
        for val in counter.values():
            if val == 2:
                num_par += 1
                if num_par == 2:
                    doble_par += 1
                    #print("Encontre otro")
                    #print(mano)
                    break
        for val in counter.values():
            if val == 4:
                poquer += 1
                #print("Encontre otro")
                #print(mano)
                break
        for val in counter.values():
            if val == 2 and traigo_par == 0:
                posible_full += 1
                traigo_par += 1
            elif val == 3:
                posible_full += 1
            if posible_full == 2:
                full += 1
                #print("Encontre otro")
                #print(mano)
                break

    probabilidad_par = pares / intentos
    probabilidad_tercia = tercia / intentos
    probabilidad_doble_par = doble_par / intentos
    probabilidad_poquer = poquer / intentos
    probabilidad_full = full / intentos
    probabilidad_color = color / intentos
    probabilidad_escalera = escalera / intentos
    probabilidad_escalera_color = escalera_color / intentos
    probabilidad_escalera_real = escalera_real / intentos
    print(f'La probabilidad de par en una mano de {tamano_mano} cartas es                   {probabilidad_par * 100}%')
    print(f'La probabilidad de doble par en una mano de {tamano_mano} cartas es             {probabilidad_doble_par * 100}%')
    print(f'La probabilidad de tercia en una mano de {tamano_mano} cartas es                {probabilidad_tercia * 100}%')
    print(f'La probabilidad de escalera en una mano de {tamano_mano} cartas es              {probabilidad_escalera * 100}%')
    print(f'La probabilidad de color en una mano de {tamano_mano} cartas es                 {probabilidad_color * 100}%')
    print(f'La probabilidad de full en una mano de {tamano_mano} cartas es                  {probabilidad_full * 100}%')
    print(f'La probabilidad de poquer en una mano de {tamano_mano} cartas es                {probabilidad_poquer * 100}%')
    print(f'La probabilidad de escalera de color en una mano de {tamano_mano} cartas es     {probabilidad_escalera_color * 100}%')
    print(f'La probabilidad de escalera real en una mano de {tamano_mano} cartas es         {probabilidad_escalera_real * 100}%')

if __name__ == '__main__':
    #barajas = crear_baraja()
    #print(baraja)
    #mano = obtener_mano(barajas, 5)
    #print(mano)
    tamano_mano = int(input('De cuantas cartas se compone la mano: '))
    intentos = int(input('Cuantos intentos quieres simular: '))

    main(tamano_mano, intentos)



Aquí mi solución del reto, la probabilidad obtenida es de 0.005108. Es más alta que la de algunos compañeros, porque considero que el as puede valer 1 o 14 según beneficie!

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 in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))

    return barajas

def obtener_mano(barajas, num_cartas):
    mano = random.sample(barajas, num_cartas) # Dentro de una coleccion escoge una muestra, sin sustitucion.

    return mano

def main(tam_mano, intentos):
    barajas = crear_baraja()

    manos = [] # Muchas manos generadas.

    for _ in range(intentos):
        mano = obtener_mano(barajas, tam_mano)
        manos.append(mano)

    corridas = 0

    conversion = {'2':2, '3': 3, '4':4, '5':5, '6':6, '7':7, '8':8, 
                  '9':9, '10':10,'jota': 11, 'reina':12, 'rey':13, 
                  }

    for mano in manos:
        # Convertimos cartas a equivalente numerico.
        
        valores = []
        contador = 0
        flag = True

        for carta in mano:
            if carta[1] == 'as':
                valores.append(1)
                valores.append(14)
            else:
                valores.append(conversion.get(carta[1]))

        valores.sort()
        
        for i, j in enumerate(valores[:-1]):
            if 1 in valores:
                if j + 1 == valores[i+1]:
                    contador += 1
                if contador + 2 == len(valores) and flag:
                    corridas += 1
                    flag = False
            else:
                if j + 1 == valores[i+1]:
                    contador += 1
                if contador + 1 == len(valores):
                    corridas += 1
                
    print(f"La probabilidad es: {corridas / intentos}")
        
if __name__ == '__main__':
    barajas = crear_baraja()
    tam_mano = int(input('De cuantas cartas sera la mano: '))
    intentos = int(input('Cuantas simulaciones para calcular la probabilidad: '))

    main(tam_mano, intentos)

Lo he pasado peor aprendiendo terminología de cartas que con el código jajajaja

Mi solución. Todavía se puede depurar un poco.

import random
FIGURAS = ['picas', 'diamantes', 'corazones', 'tréboles']
NUMEROS = ['As','2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

def crear_baraja():
    baraja = []
    for figura in FIGURAS:
        for numero in NUMEROS:
            baraja.append((figura, numero))
    return baraja

def obtener_mano(baraja, tamano_mano):
    mano = random.sample(baraja,tamano_mano)
    return mano

def probar_escalera(mano):
    solo_numeros = []
    for elemento in mano:
        solo_numeros.append(elemento[1])
    escalera = []
    
    for elemento in solo_numeros:
        escalera.append(NUMEROS.index(elemento))
    
    escalera = sorted(escalera)

    #print(mano)
    #print(solo_numeros)
    #print(escalera)

    if escalera[4] - escalera[3] == 1 and escalera[3] - escalera[2] == 1 and escalera[2] - escalera[1] == 1 and escalera[1] - escalera[0] == 1:
        return True
    else:
        return False

def probar_escalera_real(mano):
    solo_numeros = []
    for elemento in mano:
        solo_numeros.append(elemento[1])
    escalera = []
    if '10' in solo_numeros and 'J' in solo_numeros and 'Q' in solo_numeros and 'K' in solo_numeros and 'As' in solo_numeros:
        return True
    else:
        return False

def probar_color(mano):
    ordenado = sorted(mano)
    if ordenado[0][0] == ordenado[-1][0]:
        return True
    else:
        return False


def main():
    baraja = crear_baraja()
    manos = []
    pares = 0
    dos_pares = 0
    terna = 0
    poker = 0
    full = 0
    color = 0
    escalera = 0
    escalera_color = 0
    escalera_real = 0 
    otro = 0
    
    for i in range(pruebas):
        mano = obtener_mano(baraja, cartas)
        #print(mano)
        manos.append(mano)
        valores = []
        cuenta = []

        #color = ''
        ordenado = sorted(mano)
        #print(ordenado[0][0] , ordenado[-1][0])
        for i in range(len(mano)):
            valores.append(mano[i][1])
        for i in range(len(valores)):
            cuenta.append(valores.count(valores[i]))
        #print(valores)
        #print(cuenta)

        if cuenta.count(1) == 5 and not probar_escalera(mano) and not probar_escalera_real(mano) and not probar_color(mano):
            continue
        elif probar_color(mano) and probar_escalera_real(mano):
            escalera_real += 1
            #print(mano) 
        elif probar_color(mano) and probar_escalera(mano):
            escalera_color += 1
            #print(mano)
        elif probar_color(mano):
            color += 1
        elif probar_escalera(mano):
            escalera += 1
            #print(mano)
        elif cuenta.count(2) == 2 and cuenta.count(1) == 3:
            pares += 1
        elif cuenta.count(2) == 4:
            dos_pares += 1
        elif cuenta.count(3) == 3 and cuenta.count(1) == 2:
            terna += 1
        elif cuenta.count(4) == 4:
            poker += 1
        elif cuenta.count(3) == 3 and cuenta.count(2) == 2:
            full += 1
        
        else:
            otro += 1
    
    
    print(f'Pruebas realizadas: {pruebas}')
    
    print(f'Probabilidad de obtener un par: {pares/pruebas}')
    print(f'Probabilidad de obtener dos pares: {dos_pares/pruebas}')
    print(f'Probabilidad de obtener una Terna: {terna/pruebas}')
    print(f'Probabilidad de obtener una Escalera: {escalera/pruebas}')
    print(f'Probabilidad de obtener Póker: {poker/pruebas}')
    print(f'Probabilidad de obtener Full: {full/pruebas}')
    print(f'Probabilidad de obtener Color: {color/pruebas}')
    print(f'Probabilidad de obtener una Escalera de Color: {escalera_color/pruebas}')
    print(f'Probabilidad de obtener una Escalera Real: {escalera_real/pruebas}')
            
if __name__ == '__main__':
    cartas = 5
    pruebas = int(input('¿Cuántas veces va a repetir la prueba? '))
    main()

Añadiendo algo al reto de la clase, realicé un programa que calcula las probabilidades de obtener 8 manos de poker 😃

Link del repositorio: https://github.com/lowssy/poker-hands

Mi solucion al reto, se muestran las probabilidades que se tiene de una escalera o un flush en una mano y se muestran tambien las manos:

Cuantos intentos para calcular la probabilidad: 2000
[(‘espada’, ‘7’), (‘espada’, ‘8’), (‘rombo’, ‘9’), (‘espada’, ‘J’), (‘corazon’, ‘10’)]
[(‘corazon’, ‘6’), (‘espada’, ‘5’), (‘corazon’, ‘4’), (‘corazon’, ‘3’), (‘rombo’, ‘2’)]
[(‘espada’, ‘10’), (‘rombo’, ‘9’), (‘trebol’, ‘J’), (‘espada’, ‘8’), (‘corazon’, ‘Q’)]
[(‘espada’, ‘8’), (‘rombo’, ‘7’), (‘corazon’, ‘6’), (‘espada’, ‘5’), (‘espada’, ‘4’)]
La probabilidad de obtener una escalera en una mano es 0.002
La probabilidad de obtener un flush en una mano es 0.0

import collections
import random

PALOS = ['espada',  'corazon', 'rombo', 'trebol']
VALORES = ['1', '2' ,'3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    return barajas

def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)
    return (mano)  


#Si la diferencia entre indices mayor y menor de la mano, comparado con la lista VALORES, es 4 significa que es una corrida
def es_corrida(valores):
    corrida = []
    for valor in valores:
        corrida.append(VALORES.index(valor))   #Calculo del indice de cada carta en la lista Valores
    if (max(corrida) - min(corrida)) == 4:
        return True
    return False       
   

def main(intentos):
    baraja = crear_baraja()
    manos = []
    for _ in range(intentos):
        mano = obtener_mano(baraja, 5)
        manos.append(mano)
    escalera = 0
    flush = 0    
    for mano in manos:
        palo = []
        valores = []
        for carta in mano:
            palo.append(carta[0])
            valores.append(carta[1])
        counter_palo = dict(collections.Counter(palo))
        counter_valores = dict(collections.Counter(valores))
        if es_corrida(valores) and (len(counter_valores) == 5) :  # Calcula si se tiene una corrida, debe tener 5 cartas diferentes
            print(mano)
            escalera += 1 
            if len(counter_palo) == 1:  # Si la longitud del diccionario es 1, significa que solo hay un palo en la mano
                flush += 1
    probabilidad_corrida = escalera / intentos
    probabilidad_flor = flush / intentos            
    print(f'La probabilidad de obtener una escalera en una mano es {probabilidad_corrida}')
    print(f'La probabilidad de obtener un flush en una mano es {probabilidad_flor}')
        
    
if __name__ == '__main__':
    intentos = int(input('Cuantos intentos para calcular la probabilidad: '))
    main(intentos)
#Al resultado debo multiplicarlo x100 = para ver en porcentaje

import random
import collections

from typing import Counter

PALOS = ['espada', 'corazon', 'rombo', 'trebol']
VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey']

def crear_baraja(): #función que va ayudar a hacer toda nuestras barajas
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    return barajas

def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)

    return mano
    #random.sample permite tener número aleatorio pero sin repetir

def main(tamano_mano, intentos):
    barajas = crear_baraja()

    manos = [] #va guardar todas las manos que vamos a tener en nuestra simulación
    for _ in range(intentos): #Se va correr la simulación tantas veces lo haya pedido el usuario
        mano = obtener_mano(barajas, tamano_mano)#le pasamos la barajas de la línea 20, y el tmaaño de mano que pidió el usuario
        manos.append(mano)

#ahora se debe calcular que nos salga un par, dentro de una mano de cualquier tamaño
#Si tengo 5 barajas, ver la posibilidad que salga un par

    pares = 0
    for mano in manos: #debemos ir por cada mano en nuestras manos
        valores = [] #guardamos los valore
        for carta in mano:
            valores.append(carta[1]) #índice 1, porque tengo tuplas de palo(0) y valor(1)
        
        counter = dict(collections.Counter(valores))
        #print(counter) ver la simulación
        for val in counter.values():
            if val == 2: # si se encuentra un par
                pares += 1
                break
        
    probabilidad_par = pares / intentos 
    print(f'La probabilidad de obtener un par en la mano de {tamano_mano} barajas es {probabilidad_par}')



if __name__ == '__main__':
    tamano_mano = int(input('De cuantás barajas será la mano: '))
    intentos = int(input('Cuantos intentos para calcular la probabilidad: '))

    main(tamano_mano, intentos)

    barajas = crear_baraja()
    mano = obtener_mano(barajas,5)
    #print(barajas)
    #print(mano)

Si a alguien le sirve, usando el modulo pprint podemos imprimir de manera mas agradable a la vista un array o diccionario de python. Anexo código y ejemplo de salida

Buscando, vi que la corrida es la escalera de color. Aquí mi humilde aporte:

import random

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 in PALOS:
        for valor in VALORES:
            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 = []
    escalera = 0

    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
       
        es_escalera = escalera_colores(mano)

        if es_escalera:
            escalera += 1



    probabilidad_escalera = escalera / intentos
    print(f'La probabilidad de obtener una escalera en una mano de {tamano_mano} barajas es {probabilidad_escalera}')


def mismo_palo(lista):
    return all([a_tuple[0] for a_tuple in lista])


def check_consecutivos(lista):
    return sorted(lista) == list(range(min(lista), max(lista)+1))

def escalera_colores(mano):
   
    #Convierto los valores a numeros enteros
    valores = [element[1] for element in mano]
    valores_enteros = []

    for element in valores:
        if element == 'as':
            element = 1
        elif element == 'jota':
            element = 11
        elif element == 'reina':
            element = 12
        elif element == 'rey':
            element = 13

        element = int(element)
        valores_enteros.append(element)
    
    consecutivos = check_consecutivos(valores_enteros)
    igual_palo = mismo_palo(mano)

    if igual_palo and consecutivos:
        return True
    else:
        return False





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)

Probabilidad de poker con solo una baraja: ~1 de cada 5000 juegos

Les comparto mi código
Cuantas manos: 5
Cuantos intentos: 1000000
Obtener par es 0.471189 en porcentaje 47.12
Obtener doble par es 0.047665 en porcentaje 4.77
Obtener trica es 0.022727 en porcentaje 2.27
Obtener escalera es 0.00407 en porcentaje 0.41
Obtener color es 0.002 en porcentaje 0.2
Obtener full house es 0.001472 en porcentaje 0.1472
Obtener poker es 0.00024 en porcentaje 0.024
Obtener escalera de color es 2e-05 en porcentaje 0.002
Obtener escalera real es 3e-06 en porcentaje 0.0003

import random
import collections

PALOS = ['espada','corazon','rombo','trevol']
VALORES = ['ass','2','3','4','5','6','7','8','9','10','jota','reina','rey']

def crear_baraja():
    barajas = []

    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo,valor))
    return barajas

def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)
    return mano

def comprobar_escalera(escalera):
    #print(f'es {escalera}')
    valor = 1
    si_es_escalera = 0
    for pasos in escalera:
        if si_es_escalera == 5:
            break
        else:
            if pasos == valor:
                valor +=1
                si_es_escalera +=1
            else:
                valor = pasos + 1
                si_es_escalera = 1

    if si_es_escalera == 5:
        #print(f'SI ES ESCALERA {si_es_escalera}')
        return True
    else:
        return False

def analizando_escalera(valores):
    enumerando_escalera = []
    for cambiando_a_numero in valores:
        if cambiando_a_numero == 'ass':
            enumerando_escalera.append(1)
            enumerando_escalera.append(14)
        elif cambiando_a_numero == '2':    
            enumerando_escalera.append(2)
        elif cambiando_a_numero == '3':    
            enumerando_escalera.append(3)
        elif cambiando_a_numero == '4':    
            enumerando_escalera.append(4)
        elif cambiando_a_numero == '5':    
            enumerando_escalera.append(5)
        elif cambiando_a_numero == '6':    
            enumerando_escalera.append(6)
        elif cambiando_a_numero == '7':    
            enumerando_escalera.append(7)
        elif cambiando_a_numero == '8':    
            enumerando_escalera.append(8)
        elif cambiando_a_numero == '9':    
            enumerando_escalera.append(9)
        elif cambiando_a_numero == '10':    
            enumerando_escalera.append(10)
        elif cambiando_a_numero == 'jota':    
            enumerando_escalera.append(11)
        elif cambiando_a_numero == 'reina':    
            enumerando_escalera.append(12)
        elif cambiando_a_numero == 'rey':    
            enumerando_escalera.append(13)

    comprobacion = comprobar_escalera(sorted(set(enumerando_escalera)))
    if comprobacion == True:
        return 1
    else:
        return 0

def analizando_escalera_real(valores):
    diez = False
    jota = False
    reina = False
    rey = False
    ass = False

    escalera_real = 0
    for valor in valores:
        if valor == "10":
            diez = True
        elif valor == "jota":
            jota = True    
        elif valor == "reina":
            reina = True    
        elif valor == "rey":
            rey = True    
        elif valor == "ass":
            ass = True
    if diez == True and jota == True and reina == True and rey == True and ass == True:
        escalera_real += 1
    
    return escalera_real

def main(tamano_mano, intentos):
    barajas = crear_baraja()

    manos = []
    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)
    
    pares = 0
    doble_par = 0
    trica = 0
    full_house = 0 
    escalera = 0
    poker = 0
    color1 = 0
    escalera_color = 0
    escalera_real = 0

    for mano in manos:
        valores = []
        color_carta = []
        for carta in mano:
            valores.append(carta[1])
            color_carta.append(carta[0])
        counter = dict(collections.Counter(valores))
        counter_color = dict(collections.Counter(color_carta))

        par_para_full_house = 0
        for val_par in counter.values():
            if val_par == 2:
                pares += 1
                par_para_full_house = 1
                break

        verf_doble_par = 0
        for val_par in counter.values():
            
            if verf_doble_par == 2:
                break
            else:
                if val_par == 2:
                    verf_doble_par += 1
        if verf_doble_par == 2:
            doble_par += 1

        trica_para_full_house = 0
        for val_trica in counter.values():
            if val_trica == 3:
                trica += 1
                trica_para_full_house = 1
                break
        
        escalera = escalera + analizando_escalera(valores)

        if par_para_full_house == 1 and trica_para_full_house == 1:
            full_house += 1
            
        for val_poker in counter.values():
            if val_poker == 4:
                poker += 1                
                break

        hay_color = False
        for color_de_carta in counter_color.values():
            if color_de_carta == 5:
                hay_color = True
                break

        if len(counter_color) == 1:
            color1 += 1
            escalera_real = escalera_real + analizando_escalera_real(valores)
            escalera_color = escalera_color + analizando_escalera(valores)

    probabilidad_de_par = pares / intentos
    print(f'Obtener par es {probabilidad_de_par} en porcentaje {round(probabilidad_de_par*100,2)}')

    probabilidad_de_doble_par = doble_par / intentos
    print(f'Obtener doble par es {probabilidad_de_doble_par} en porcentaje {round(probabilidad_de_doble_par*100,2)}')

    probabilidad_de_trica = trica / intentos
    print(f'Obtener trica es {probabilidad_de_trica} en porcentaje {round(probabilidad_de_trica*100,2)}')

    probabilidad_de_escalera = escalera / intentos
    print(f'Obtener escalera es {probabilidad_de_escalera} en porcentaje {round(probabilidad_de_escalera*100,2)}')

    probabilidad_de_color = color1 / intentos
    print(f'Obtener color es {probabilidad_de_color} en porcentaje {round(probabilidad_de_color*100,2)}')

    probabilidad_de_full_house = full_house / intentos
    print(f'Obtener full house es {probabilidad_de_full_house} en porcentaje {round(probabilidad_de_full_house*100,4)}')

    probabilidad_de_poker = poker / intentos
    print(f'Obtener poker es {probabilidad_de_poker} en porcentaje {round(probabilidad_de_poker*100,4)}')

    probabilidad_de_escalera_color = escalera_color / intentos
    print(f'Obtener escalera de color es {probabilidad_de_escalera_color} en porcentaje {round(probabilidad_de_escalera_color*100,4)}')

    probabilidad_de_escalera_real = escalera_real / intentos
    print(f'Obtener escalera real es {probabilidad_de_escalera_real} en porcentaje {round(probabilidad_de_escalera_real*100,4)}')

if __name__ == "__main__":
    tamano_mano = int(input("cuantas manos: "))
    intentos = int(input("cuantos intentos: "))

    main(tamano_mano, intentos)

Mi solucion del reto de una escalera (tomandola como consecutiva en valores)
import random
import collections

PALOS = ['espada', 'corazon', 'rombo', 'trebol']
VALORES = [1,2,3,4,5,6,7,8,9,10,11,12,13]

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))

    return barajas
def ordenar_burbuja(mano):
    i=0
    j=0
    while i<len(mano)-1:
        while j<len(mano)-1:
            if mano[j][1]>mano[j+1][1]:
                extraMano=mano[j]
                mano[j]=mano[j+1]
                mano[j+1]=extraMano
            j=j+1
        i=i+1
        j=0
    return mano

def EsConsecutivo(manoOrdenada):
    esConsecutivoResultado=False
    i=0
    while  i<len(manoOrdenada)-1:
        if manoOrdenada[i+1][1]-manoOrdenada[i][1]==1:
            esConsecutivoResultado=True
        else:
            esConsecutivoResultado=False
            break
        i=i+1
    return esConsecutivoResultado




def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)
    
    return mano

def main(tamano_mano, intentos):
    barajas = crear_baraja()

    manos = []
    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    corridas = 0
    for mano in manos:
        #print(f'Baraja no ordenada{mano}')
        #print(f'Baraja ordenada{ordenar_burbuja(mano)}')
        corridas=corridas+1 if EsConsecutivo(ordenar_burbuja(mano)) else corridas

    probabilidad_corridas = corridas / intentos
    print(f'La probabilidad de obtener un par en una mano de {tamano_mano} barajas es {probabilidad_corridas}')


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)

Les dejo mi solucion para obtener una corrida de cartas:

La posibilidad con 5 cartas tiende a 0.005%.

def probabilidad_de_corrida(manos):
    corridas = 0
    for mano in manos:
        valores = [carta[1] for carta in mano]
        ultimo_valor = valores[len(valores) - 1]
        es_corrida = True
        for idx, valor in enumerate(valores):
            if idx != len(valores) - 1:
                siguiente_valor = valores[idx + 1]
                if valor == 13 and siguiente_valor == 1:
                    siguiente_valor = 14
                if siguiente_valor != valor + 1:
                    es_corrida = False
        if es_corrida:
            corridas += 1

    return corridas / len(manos)

Hola yo lo hice para la escalera de la siguiente forma :
1 - Creo todas las posibles ESCALERAS
2 - Ordeno los dados de menos a mayor
3 - Checkeo si el tiro esta adentro de ESCALERAS

Me queda algo asi:

<
def crear_escaleras():  #Creates all possible straights
    ESCALERAS = []
    for i in range(len(VALORES)-4):
        ESCALERAS.append([i+1, i+2, i+3, i+4, i+5])
    ESCALERAS.append([10, 11, 12, 13, 1])
    return ESCALERAS


    escalera = 0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        valores = sorted(valores)    
        if valores in ESCALERAS:
            escalera += 1   
    
    # print(f'estas son todas las posibles escaleras : \n {ESCALERAS}')
    print(f'Todas las escaleras que salieron : {escalera}')
    probabilidad_escalera = escalera / intentos
    print(f'La probabilidad de sacar una escalera \nen la primera mano es: \n {probabilidad_escalera}')


> 

Creí que tendríamos como invitado especial al Señor Oscar Barajas. 😦

Señores ✌️😄 no lo hice con todas las jugadas del poker porque tengo que priorizar ciertas cosas pero despues lo completare, creo que esta version les gustara ya que imprime las manos con emojis 💘🍀💎⚔️

import collections
import random
PALOS=['⚔️','💘','💎','🍀']
VALORES=['A','1','2','3','4','5','6','7','8','9','JOTA','REINA','REY']


def crear_baraja():
    """
    Esta funcion crea la baraja
    """
    barajas=[]
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo,valor))
    return barajas

def obtener_mano(barajas,tamano_mano):
    """
    docstring
    """
    mano=random.sample(barajas,tamano_mano)

    return mano

def main(tamano_mano,intentos):
    """
    docstring
    """
    barajas=crear_baraja()

    manos=[]
    for _ in range(intentos):
        mano=obtener_mano(barajas,tamano_mano)
        manos.append(mano)
    pares=0
    tercia=0
    poker=0
    corrida=0
    corrida_color=0
    for mano in manos:
        valores=[]
        for carta in mano:
            valores.append(carta[1])
        counter = dict(collections.Counter(valores))
        for val in counter.values():
            if val ==2:
                pares+=1
                break
            elif val == 3:
                tercia+=1
                break
            elif val == 4:
                poker+=1
                break
        lista_corrida=[]
        for keys in counter.keys():
            lista_corrida.append( VALORES.index(keys))
        lista_corrida.sort()
        if len(lista_corrida)==5:
            
            if (lista_corrida[0]+1)== lista_corrida[1] and (lista_corrida[0]+2)== lista_corrida[2] and (lista_corrida[0]+3)== lista_corrida[3] and (lista_corrida[0]+4)== lista_corrida[4]:
                corrida+=1
                if mano[0][0] == mano[1][0] and mano[1][0] == mano[2][0] and mano[2][0] == mano[3][0]  and mano[3][0] == mano[4][0]:
                    print(mano)
                    print(mano[0][0])
                    corrida_color+=1

    probabilidad_pares= pares/intentos
    probabilidad_tercias=tercia/intentos
    probabilidad_poker=poker/intentos
    probabilidad_corrida=corrida/intentos
    probabilidad_corrida_color=corrida_color/intentos

    print(f'La probabilidad de obtener un par en una mano de {tamano_mano} cartas es {probabilidad_pares},Pares en la simulacion {pares} en {intentos} intentos')
    print(f'La probabilidad de obtener una tercia en una mano de {tamano_mano} cartas es {probabilidad_tercias},tercias en la simulacion {tercia} en {intentos} intentos')
    print(f'La probabilidad de obtener un poker en una mano de {tamano_mano} cartas es {probabilidad_poker},full house en la simulacion {poker} en {intentos} intentos')
    print(f'La probabilidad de obtener un corrida de numeros en una mano de {tamano_mano} cartas es {probabilidad_corrida},corridas en la simulacion {corrida} en {intentos} intentos')
    print(f'La probabilidad de obtener un corrida de color de numeros en una mano de {tamano_mano} cartas es {probabilidad_corrida_color},corridas en la simulacion {corrida_color} en {intentos} intentos')



if __name__ == "__main__":
    tamano_mano=int(input("¿De cuantas cartas sera la mano? "))
    numero_de_intentos=int(input("¿Cuantas veces se correra la simulacion? "))
    main(tamano_mano,numero_de_intentos)

primera mano repartida:
[(‘corazon’, ‘2’), (‘corazon’, ‘4’), (‘diamante’, ‘10’), (‘espada’, ‘6’), (‘diamante’, ‘joker’)]

no voy!

Es la solución que encontré tratando de apoyarme únicamente en mi lógica (que no es muy buena). Se puede reducir mucho mas, estoy seguro que conforme avance encontrare maneras mas eficaces de resolver un mismo problema.

import random 
import collections
from typing import Text 

PALOS = ['espada', 'corazon', 'rombo', 'trebol']
VALORES =["AS", '2', '3', '4', '5','6', '7','8','9','10','J', 'Q', 'K']

def crear_baraja():
    barajas = []

    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo,valor))
    
    return barajas


def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)
 
    return mano


def separar_letras_numeros(valores, tamano_mano):
    numeros = []
    letras_aleatorias = []
    estado = 0
    indicador = 0
    respuesta = 0
    numeros_ascii = []
    temporal = 0
    numeros_lista_completa = []
    letras_as_ascii = [] 

    for e in range(len(valores)):
        # USO EL TRY EXCEPT PARA SEPARAR LOS NUMEROS DE LAS LETRAS
        try:
            numeros.append(int(valores[e]))
            numeros_lista_completa.append(int(valores[e]))

        except ValueError:
            letras_aleatorias.append(str(valores[e])) 
            # AQUI PREGUNTO " SI TENGO  UNA J AGREGO EL CODIGO EN OTRA LISTA"
            if "J" in letras_aleatorias:
                numeros_ascii.append(int(74))
            elif "Q" in letras_aleatorias:
                numeros_ascii.append(int(81))
            elif "K" in letras_aleatorias:
                numeros_ascii.append(int(107))
            elif "AS" in letras_aleatorias:
                letras_as_ascii.append(int(65))
                letras_as_ascii.append(int(83))
    
    # CON SET ELIMINO LOS ELEMENTOS REPETIDOS
    letras_as_ascii = set(letras_as_ascii)
    # CON LIST VUELVO A TRANSFORMAR A LISTA
    letras_as_ascii = list(letras_as_ascii)
    
    numeros = set(numeros)
    numeros = list(numeros)
    # CON SORT ORDENO DE MENOR A MAYOR
    numeros.sort()
    
    numeros_ascii = set(numeros_ascii)
    numeros_ascii = list(numeros_ascii)
    numeros_ascii.sort()

    # AQUI VERIFICO SI LOS NUMEROS SON ESCALERA. SI SON ESCALERA (1,2,3) ESTADO SUMA 1
    for i in range(len(numeros)- 1):
        if i + 1 <= len(numeros):
            if numeros[i+1] == numeros[i]+1:
                estado += 1

    # AQUI DESCARTO OPCIONES EN LAS QUE EXISTAN OBJETOS REPETIDOS EN LA MANO, ES DECIR SI TENGO DOS "J" 
    # YA NO SERIA UNA CORRIDA

    if len(numeros_ascii) < len(letras_aleatorias) or len(numeros) < len(numeros_lista_completa):
        respuesta = 0
    
    # ESTADO ME SUMABA 1 POR CADA ITERACION CORRECTA, ES DECIR SUMABA 1 SI EL VALOR FORMABA ESCALERA
    # AQUI SOLO LE PREGUNTO "SI TODOS LOS VALORES FORMAN ESCALERA INDICADOR ES = 1"
    if estado == len(numeros)- 1:
        indicador += 1
    
    # AQUI DESCARTO LA OPCION DE QUE TENGA UNA ESCALERA SOLO DE NUMEROS
    # POR ESO PREGUNTO SI TENGO SOLO NUMEROS Y SI ESTAN ORDENADOS(INDICADOR=1)
    if len(numeros) == tamano_mano and indicador == 1:
        respuesta = 1
        print(numeros, " SOLO NUMEROS ")
    
    # AQUI EMPIEZO CON EL "AS", NECESITO QUE  LOS NUMEROS ESTEN ORDENADOS
    if indicador == 1:
        # PREGUNTO SI LA SUMA DE LOS ELEMENTOS (LETRAS Y NUMEROS) ES IGUAL AL TAMANO ORIGINAL
        # AQUI COMO "AS" EN LA LISTA SON DOS ELEMENTOS "65,83" NECESITO EXTENDER (TAMANO_MANO+1) EL TAMANO DE LA MANO 
        # PARA EVITAR ERROR
        if  len(letras_as_ascii) + len(numeros) == tamano_mano + 1:
            # PREGUNTO SI TENGO UN 2 EN LA LISTA NUMEROS
            if 2 in numeros:
                # SI ES QUE SI PREGUNTO SI TENGO EL AS EN LETRAS
                if 65 in letras_as_ascii and 83 in letras_as_ascii:
                    temporal +=1
                
    # AQUI EMPIEZO CON LAS LETRAS (J,Q,K), IGUAL LOS NUMERO TIENEN QUE ESTAR ORDENADOS 
    if indicador == 1:
        # IGUAL PREGUNTO SI LA SUMA DE LAS DOS LISTAS ES IGUAL AL TAMANO D ELA MANO
        if len(numeros_ascii) + len(numeros) == tamano_mano:
            # PREGUNTO SI TENGO UN 10 SI ES QUE SI PREGUNTO SI TENGO J, Q Y K Y GUARDO RESPUESTA EN "temporal"
            if 10 in numeros:
                if 74 in numeros_ascii:
                    temporal += 1
                    if temporal == 1:
                        if 81 in numeros_ascii:
                            temporal += 1
                            if temporal == 2:
                                if 107 in numeros_ascii:      
                                    temporal+=1    
        else:
            respuesta = 0
    else:
        respuesta = 0

    # SI ES QUE CUMPLE LAS CONDICIONES ANTERIORES RESPUESTA SUMA 1
    if temporal >=1:
        respuesta += 1
        print(numeros, numeros_ascii, letras_as_ascii, "NUMEROS Y LETRAS")

    return respuesta


def main(tamano_mano, intentos):

    barajas = crear_baraja()
    probabilidad = 0
    manos = []

    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)
    pares = 0 

    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])
        # AQUI INVOCO Y GUARDO "RESPUESTA" EN "CORRIDA"
        corridas = separar_letras_numeros(valores, tamano_mano)
        if corridas >= 1:
            print(" SON CORRIDAS")
            # "PROBABILIDAD" SIRVE PARA CONTAR CUANTAS CORRIDAS ME SALEN, LUEGO SE LE PROMEDIA
            probabilidad += 1

        counter = dict(collections.Counter(valores))
        for val in counter.values():
            if val == 2:
                pares+=1
                break

    probabilidad_corridas = probabilidad / intentos
    print(f'La probabilidad de obtener corridas en una mano de {tamano_mano} es {probabilidad_corridas}')
    probabilidad_par = pares / intentos
    print(f'La probabilidad de obtener un par en una mano de {tamano_mano} es {probabilidad_par}')


if __name__=='__main__':
    tamano_mano = int(input("De cuantas barajas sera la mano? "))
    intentos = int(input("Cuantos intentos: "))
    main(tamano_mano, intentos)

Resultado con una simulación de 10,000,000 de intentos:

La probabilidad de encontrar pair es del: 0.4226727
La probabilidad de encontrar two_pair es del: 0.0475905
La probabilidad de encontrar three_of_a_kind es del: 0.0211279
La probabilidad de encontrar straight es del: 0.0035663
La probabilidad de encontrar flush es del: 0.0019867
La probabilidad de encontrar full_house es del: 0.001436
La probabilidad de encontrar four_of_a_kind es del: 0.0002324
La probabilidad de encontrar straight_flush es del: 1.41e-05
La probabilidad de encontrar royal_flush es del: 1.9e-06

Código, perdonen el spanglish 😄

import random
import collections

PALOS = ['espada', 'corazon', 'diamante', 'trebol']
VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey']
Juegos = {'pair': 0, 'two_pair': 0, 'three_of_a_kind': 0, 'straight': 0,
          'flush': 0, 'full_house': 0, 'four_of_a_kind': 0, 'straight_flush': 0,
          'royal_flush': 0}
CARD_VALUES = {}


def crear_baraja():
    baraja = []
    for palo in PALOS:
        for valor in VALORES:
            baraja.append((palo, valor))

    return baraja


def obtener_mano(baraja, tam_mano):
    mano = random.sample(baraja, tam_mano)

    return mano


def set_card_values():
    count = 1
    for symbol in VALORES:
        CARD_VALUES[symbol] = count
        count += 1


def card_to_number(card):
    if card in CARD_VALUES:
        return CARD_VALUES[card]
    else:
        raise ValueError


def is_royal_flush(values):
    max_value = 13
    if len(values) < 13:
        royal_flush_values = [(13 - i) for i in range(0, len(values) - 1)]
        royal_flush_values.append(1)
    elif len(values) == 13:
        royal_flush_values = [(13 - i) for i in range(0, len(values))]
    else:
        raise ValueError

    royal_flush_values = sorted(royal_flush_values)

    if values == royal_flush_values:
        return 1


def obtener_consecutivos(num):
    values = []
    for card in num:
        values.append(card_to_number(card))

    values = sorted(values)

    if is_royal_flush(values) == 1:
        return 1

    reference = min(values)
    count = 1
    flag = False
    len_hand = len(values)
    while not flag:
        if reference + 1 == values[count]:
            reference += 1
            count += 1
        else:
            flag = True

        if count == len_hand:
            return 0

    return -1


def obtener_numeros(counter):
    numbers = []
    for card in counter.keys():
        numbers.append(card[1])

    return dict(collections.Counter(numbers))


def obtener_palos(counter):
    palos = []
    for card in counter.keys():
        palos.append(card[0])

    return dict(collections.Counter(palos))


def full_house(counter):
    num = obtener_numeros(counter)

    if 2 in num.values() and 3 in num.values():
        Juegos['full_house'] += 1
        return True

    return False


def two_pair(counter):
    num = obtener_numeros(counter)

    two_two = 0
    for valor in num.values():
        if valor == 2:
            two_two += 1

    if two_two == 2:
        Juegos['two_pair'] += 1
        return True

    return False


def pair(counter):
    num = obtener_numeros(counter)

    if 2 in num.values():
        Juegos['pair'] += 1
        return True

    return False


def three_of_a_kind(counter):
    num = obtener_numeros(counter)

    if 3 in num.values():
        Juegos['three_of_a_kind'] += 1
        return True

    return False


def four_of_a_kind(counter):
    num = obtener_numeros(counter)

    if 4 in num.values():
        Juegos['four_of_a_kind'] += 1
        return True

    return False


def royal_flush(counter):
    num = obtener_numeros(counter)
    pal = obtener_palos(counter)

    if 5 in pal.values():
        result = obtener_consecutivos(num)
        if result == 1:
            Juegos['royal_flush'] += 1
            return True

    return False


def straight_flush(counter):
    num = obtener_numeros(counter)
    pal = obtener_palos(counter)

    if 5 in pal.values():
        result = obtener_consecutivos(num)
        if result == 0:
            Juegos['straight_flush'] += 1
            return True

    return False


def flush(counter):
    pal = obtener_palos(counter)

    if 5 in pal.values():
        Juegos['flush'] += 1
        return True

    return False


def straight(counter):
    num = obtener_numeros(counter)

    result = obtener_consecutivos(num)
    if result == 0:
        Juegos['straight'] += 1
        return True

    return False


def check_game(counter):
    func = [full_house, two_pair, pair, three_of_a_kind, four_of_a_kind,
            royal_flush, straight_flush, straight, flush]

    flag = False
    count = 0
    while not flag:
        try:
            flag = func[count](counter)
        except IndexError:
            flag = True

        count += 1


def main(tam_mano, intentos):
    baraja = crear_baraja()

    mano = []
    for vez in range(intentos):
        mano.append(obtener_mano(baraja, tam_mano))

    for juego in mano:
        valores = []
        for carta in juego:
            valores.append(carta)

        counter = dict(collections.Counter(valores))
        check_game(counter)


if __name__ == '__main__':
    try:
        tam_mano = int(input('De cuantas cartas será la mano: '))
    except ValueError:
        tam_mano = 5

    try:
        intentos = int(input('Cuantos intentos para calcular la probabilidad: '))
    except ValueError:
        intentos = 1000

    set_card_values()
    main(tam_mano, intentos)

    for key, value in Juegos.items():
        print('La probabilidad de encontrar {} es del: {}'.format(key, value / intentos))

dentro de collections, existe una colección llamada Counter.

La función sample dentro de random, nos permite tener muestras únicas de una colección.

Nuestro poder, es que se puede determinar qué tan probable son ciertas situaciones.

RETO CUMPLIDO
Una corrida o flush es una mano que contiene todas las cartas del mismo palo, no necesariamente consecutivas.

def main(hand_size, attempts):
    deck = create_deck()

    hands = []
    for _ in range(attempts):
        hand = get_hand(deck, hand_size)
        hands.append(hand)

    flush = 0

    for hand in hands:
        suits = []
        for card in hand:
            suits.append(card[0])

        counter = dict(collections.Counter(suits))
        for value in counter.values():
            if value == hand_size:
                flush += 1
            break

    probability_flush = flush / attempts
    print('La probabilidad de obtener una corrida en una mano de {} cartas es {}'.format(hand_size, probability_flush))

Recordemos que en la corrida deben ser 5 cartas del mismo palo, independientemente de si son consecutivas, lo que significa que pueden ser de cualquier valor, lo único que importa es que sean del mismo palo.
⠀⠀⠀⠀⠀⠀⠀⠀⠀
Entonces, para esto lo que hice fue ocupar el mismo metodo del profesor aroesti, solo que los aplique para los palos.

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 in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    return barajas

def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)
    
    return mano

def calc_probabilidades(manos, intentos):

    pares = 0
    escalera_color = 0
    
    for mano in manos:
        valores = []
        palos = []

        for carta in mano:    
            
            valores.append(carta[1])
            palos.append(carta[0])
             
        counter_palos = dict(collections.Counter(palos))
        for val in counter_palos.values():
            if val == 5:
                escalera_color += 1
        
        counter_valores = dict(collections.Counter(valores))

        for val in counter_valores.values():
            if val == 2:
                # Obtener par
                pares += 1
        
    print(f'La probabilidades de obtener una par en una mano de {tamano_mano} barajas es {pares/intentos}')
    print(f'La probabilidades de obtener una escalera de color en una mano de {tamano_mano} barajas es {escalera_color/intentos}')

def main(tamano_mano, intentos):
    barajas = crear_baraja()

    manos = []

    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    calc_probabilidades(manos, intentos)
    
    
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)

Para darle más aleatoriedad se pude usar el comando shuffle para simular que cada que se reparte una mano se revuelven las cartas, quedaría así la función:

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))

    random.shuffle(barajas)

    return barajas

Le realicé una modificación al reto añadiéndole que la corrida tiene que ser del mismo palo, las probabilidades son aun mas bajas cuando se aumenta el número de cartas de la mano pero la probabilidad aumenta si se aumentan los intentos.

def main(tamano_mano, intentos):
    barajas = crear_baraja()
    manos = []

    for _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)

    corridas = 0

    for mano in manos:
        es_corrida = True
        es_mismo_palo = True
        valores_mano = []
        

        for carta in mano:
            valores_mano.append(carta[0])

        for i in range(tamano_mano):
            if(mano[0][1] != mano[i][1]):
                es_mismo_palo = False

        if(es_mismo_palo):
            index = VALORES.index(valores_mano[0])
            for i in range(1,tamano_mano):
                if(index+i == 13):
                    index = -i

                proxima = VALORES[index + i]
                if(proxima not in valores_mano):
                    es_corrida = False
                    break

            if(es_corrida):
                print(mano)
                corridas += 1  
 

    probabilidad_corrida = corridas / intentos
    print(f'La probabilidad de obtener una corrida es: {probabilidad_corrida}' )

Para los que no entendieron como funciona “sample” un ejemplo: Supongamos que tenemos 4 pelotas, una roja, azul, verde y amarrilla. Si seleccionamos pelotas al azar con sustitución la primera pelota que se escoja será roja, como no hay sustitución se vuelve a meter, la segunda que sale es esta misma. Si fuera sin sustitución la segunda será si o si una diferente a la roja por que está ya fue seleccionada

Aquí mi código de como obtuve una escalera:

import random
import collections


STICKS = ['espada', 'corazón', 'rombo', 'trebol']
VALUES = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']


def create_deck():
    deck = []
    for stick in STICKS:
        for value in VALUES:
            deck.append((stick, value))

    return deck


def get_hand(deck, hand_size):
    hand = random.sample(deck, hand_size)

    return hand


def is_stair(hand_values):
    stair_values = hand_values.copy()

    for i, val in enumerate(stair_values):
        if val in ['A', 'J', 'Q', 'K']:
            stair_values[i] = {'A': 1, 'J': 11, 'Q': 12, 'K': 13}.get(val)
        else:
            stair_values[i] = int(val)
    stair_values.sort()
    
    for i in range(len(stair_values) - 1):
        if stair_values[i + 1] != stair_values[i] + 1:
            return False

    return True


def main(hand_size, attempts):
    deck = create_deck()
    hands = []
    
    for _ in range(attempts):
        hand = get_hand(deck, hand_size)
        hands.append(hand)

    pairs = 0
    stairs = 0
    for hand in hands:
        values = []
        for cart in hand:
            values.append(cart[1])
            
        if is_stair(values):
            stairs += 1
            
        counter = dict(collections.Counter(values))
        for val in counter.values():
            if val == 2:
                pairs += 1

    pair_probability = pairs / attempts
    stair_probability = stairs / attempts
    print(f'Pair probability: {pair_probability}')
    print(f'Stair probability: {stair_probability}')


if __name__ == '__main__':
    _hand_size = int(input('Hand size: '))
    _attempts = int(input('Attempts: '))
    main(_hand_size, _attempts)

Hola compañeros, les comparto mi código para poder calcular la probabilidad para todas las manos de poker. Primero las funciones helper para el main:

import collections
import random

SUITS = ['Club', 'Diamond', 'Spade', 'Heart']
RANKS = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace']

def create_deck():
    """This method creates a deck of 52 cards based on the constants 
    SUITS and RANKS

    Returns : 
        deck : List of tuples with all the combinations for the 52 card deck
    """
    deck = []
    for suit in SUITS:
        for rank in RANKS:
            deck.append((suit, rank))
    
    return deck

def get_hand(deck):
    """This method takes 5 cards from the deck. The size of the hand
    is based on the game Texas Hold'em.

    Arguments :
        deck : The list of all the cards

    Returns : 
        hand : List of 5 cards selected randomly
    """
    hand = random.sample(deck, 5)
    return hand

Ahora el main:

def main(attempts):
    """ This method will generate as many hands of poker as specified in attempts,
    and then will calculate the probability for all the valid possible   
    combinations of cards in Poker.

    Arguments : 
        attempts : Number of simulations for this 

    """

    deck = create_deck()
    hands = []
    for _ in range(attempts):
        hand = (get_hand(deck))
        hands.append(hand)
    
    # We create a dictionary for every combination for Poker.
    # Every key has a value assigned that saves the total of hands in the attempts
    list_hands = {
        'Pair' : 0,
        'Two pairs' : 0,
        'Three of a kind' : 0,
        'Straight' : 0,
        'Flush' : 0,
        'Full house' : 0,
        'Four of a kind' : 0,
        'Straight flush' : 0,
        'Royal flush' : 0,
    }

    # Set the values for each card to verify later if the cards are consecutive
    value_cards = {}
    value = 2
    for card in RANKS:
        new_value = {card : value}
        value_cards.update(new_value)
        value += 1

    # Evaluate each hand
    for hand in hands:
        values_hand = []
        suits_hand = []
        for card in hand:
            suits_hand.append(card[0])
            values_hand.append(card[1])

        # Set the counters for the values of the cards and the 
        values_counter = dict(collections.Counter(values_hand))
        suits_counter = dict(collections.Counter(suits_hand))

        if 2 in values_counter.values():
            # Verify if there is a 3 involved for a Full House
            if 3 in values_counter.values():
                list_hands['Full house'] += 1

            # Count the quantity of pairs on the same hand to know if it is 
            # a 'Pair of a 'Two Pairs'
            pairs = 0
            for val in values_counter.values():
                if val == 2:
                    pairs += 1
            if pairs  == 1:
                list_hands['Pair'] += 1
            elif pairs == 2:
                list_hands['Two pairs'] += 1
        
        elif 3 in values_counter.values():
            list_hands['Three of a kind'] += 1

        elif 4 in values_counter.values():
            list_hands['Four of a kind'] += 1
        else:
            # Ordered the cards by values
            ordered_values = []
            for i in values_hand:
                ordered_values.append(value_cards[i])
            ordered_values = sorted(ordered_values)
            difference  = max(ordered_values) - min(ordered_values)
            if difference == 4:
                if 5 in suits_counter.values():
                    if min(ordered_values) == 10:
                        list_hands['Royal flush'] += 1
                    else:
                        list_hands['Straight flush'] += 1
                else:
                    list_hands['Straight'] += 1
            else:
                if 5 in suits_counter.values():
                    list_hands['Flush'] += 1
            # Straight Flush
            # Royal Flush
    
    # Calculate the probability of obtaining each hand
    print('The probabilities for all the following hands are : ')
    for key, val in list_hands.items():
        probability = val / attempts
        print(f'{key} => {probability}')

if __name__ == '__main__':
    
    attempts = int(input('Define how many times the simulation will run: '))
    
    main(attempts)

En el programa original hay un caso que no se considera de acuerdo al objetivo propuesto por el profesor (contar únicamente las manos donde hayan pares, no tercias). Si en una mano de 5 cartas, por ejemplo, sale un par y una tercia, esa mano se contaría como una ocurrencia del evento debido al break cuando se encuentra un valor de 2 en el ciclo de conteo sin verificar el resto de valores.

Esto es de acuerdo a como yo entendí la definición del problema 😅, aunque también se puede entender como la probabilidad de que la mano tenga al menos un par, sin importar que éste esté acompañado por tercias o no.

Fue lo mas que me pude aproximar

Simulación de Barajas

Es un ejercicio que nos sirve para simular un juego de cartas como el poker en donde se tienen 4 palos o figuras. La probabilidad de que salgan ciertas combinaciones de cartas en al recibir 5 cartas del total se va reduciendo por lo que el valor de esa combinación aumenta para ganar el juego. A continuación les dejo una imagen con las combinaciones y su valoración.

No sabía cómo completar el reto, así que tomé de referencia este tutorial de un chico de la comunidad!
https://platzi.com/tutoriales/1835-programacion-estocastica/7895-simulando-todas-las-manos-del-poker/

import random
import collections

PALOS = ["corazon", "trebol", "diamante", "picas"]
VALORES= ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    
    return barajas

def obtener_mano(barajas, tamano_mano):
    mano = random.sample(barajas, tamano_mano)

    return mano

def simular_manos(baraja, intentos, tamano_mano):
    manos = []

    for _ in range(intentos):
        mano = obtener_mano(baraja, tamano_mano)
        manos.append(mano)

    return manos

#JUGADAS QUE NECESITAN EL counter.value() PARA SABER SI ALGÚN VALOR SE HA REPETIDO
# Par, trío, doble par y poker

# Se arregla el algoritmo del par para que me diga cuándo  encuentra un par (2 iguales)
# ya que se necesita el counter.value
def par(valores_acomulados):
    for val in valores_acomulados:
        if val == 2:
            return 1
        return 0

# Se arregla el algoritmo del trío para que me diga cuándo  encuentra un trío (3 iguales)
# ya que se necesita el counter.value
def trio(valores_acomulados):
    for val in valores_acomulados:
        if val == 3:
            return 1
        return 0

# Se arregla el algoritmo del poker para que me diga cuándo  encuentra un poker (4 iguales)
# ya que se necesita el counter.value
def poker(valores_acomulados):
    for val in valores_acomulados:
        if val == 4:
            return 1
        return 0

#Cómo se hace con el DOBLE PAR? Necesitamos evitar que la función termine
# al encontrar uno y agregar un contador que recuerde cuantaa veces hubo par

def doble_par(valores_acomulados):
    contador = 0   #Contador
    for val in valores_acomulados:
        if val == 2:
            contador += 1 #En vez de retornar 1, cuenta las veces que hubo par
    if contador == 2: #Si cuenta 2 pares, retorna 1, de lo contrario retorna 0
        return 1
    else:
        return 0


# JUGADAS QUE NECESITAN LA FUNCIÓN color(palos) PARA ENCONTRAR LOS PALOS DE LA MANO QUE HAN SALIDO
# Color

#Guarda el primer palo
def color(palos):
    palo_carta_1 = palos[0] 
    for palo in palos:
        if palo_carta_1 != palo: #Lo compara con el resto de palos
            return 0
    return 1
        
#JUGADAS QUE REQUIEREN LOS VALORES QUE HAN SALIDO EN LAS CARTAS DE ESA MANO
# Escalera 

def escalera(valores):
    valores_numericos = []
    for valor in valores:
        try:
            valor_numerico = int(valor)
            valores_numericos.append(valor_numerico)

        except ValueError:
            if valor == "J":
                valores_numericos.append(11)
            elif valor == "Q":
                valores_numericos.append(12)
            elif valor == "K":
                valores_numericos.append(13)
            elif valor == "A":
                valores_numericos.append(1)
                valores_numericos.append(14)
    
    valores_numericos.sort()
    n_valores = len(valores_numericos)

    for i in range(n_valores - 1): #Se resta el 1 ya que no hace falta comparar los dos últimos valores
        if valores_numericos[i] != valores_numericos[i + 1] - 1:
            if valores_numericos[i] != 1: #Se usa para asegurarnos que, en dado caso que salga una escalera real, se haga la resta 13-14 (K -A) y no 1 - 10 (A -10)
                return 0
        i += 1
    return 1

#JUGADAS QUE NECESITAN SABER SI UN VALOR SE REPITIÓ, SABER LOS PALOS QUE HAN SALIDO Y LOS VALORES DE LAS CARTAS.
#Full, Escalera de color y Escalera real de color

def full(valores_acomulados):
    un_par = par(valores_acomulados)
    un_trio = trio(valores_acomulados)
    if un_par == 1 and un_trio == 1: #Se quiere saber si hay un par y un trío
        return 1
    else:
        return 0

def escalera_de_color(valores, palos):
    una_escalera = escalera(valores)
    un_color = color(palos)
    if una_escalera == 1 and un_color == 1: #Se quiere saber si hay un color y  una escalera
        return 1
    else:
        return 0

def escalera_real_de_color(valores, palos):
    una_escalera_de_color = escalera_de_color(valores, palos)
    if una_escalera_de_color == 1:  #Se pregunta si hay una escalera de color
        if "10" in valores and "A" in valores:
            return 1
        else:
            return 0
    return 0


def main(tamano_mano, intentos):
    barajas = crear_baraja()

    # Creo un diccionario que almacene todas las jugadas posibles
    jugadas = {"Par": 0,
                "Doble par": 0,
                "Trío" : 0,
                "Escalera": 0,
                "Color": 0,
                "Full": 0,
                "Poker": 0,
                "Escalera de color": 0,
                "Escalera real de color": 0,
                }

    manos = simular_manos(barajas, intentos, tamano_mano)

    # manos = []
    # for _ in range(intentos):
    #     mano = obtener_mano(barajas, tamano_mano)
    #     manos.append(mano)
    

    # pares = 0
    for mano in manos:
        valores = []
        palos = []
        for carta in mano:
            valores.append(carta[1])
            palos.append(carta[0])
        
        counter = dict(collections.Counter(valores))

        jugadas["Par"] += par(counter.values())
        jugadas["Trío"] += trio(counter.values())
        jugadas["Doble par"] += doble_par(counter.values())
        jugadas["Poker"] += poker(counter.values())
        jugadas["Color"] += color(palos) #Lista de los palos de la mano
        jugadas["Escalera"] += escalera(valores)
        jugadas["Full"] += full(counter.values())
        jugadas["Escalera de color"] += escalera_de_color(valores, palos)
        jugadas["Escalera real de color"] += escalera_real_de_color(valores, palos)

    for jugada in jugadas.keys():
        probabilidad = jugadas[jugada] / intentos
        print(f'La probabilidad de sacar {jugada} en una mano de {tamano_mano} cartas es de {probabilidad}')

        # print(counter)
        # for val in counter.values():
        #     if val == 2:
        #         pares += 1
        #         break

    # probabilidad_par = pares / intentos

    # print(f'La probabilidad de obtener un par en una mano de {tamano_mano} cartas es de {probabilidad_par}') 

if __name__ == "__main__":
    tamano_mano = int(input("De cuantas cartas será la mano?: "))
    intentos = int(input("De cuantos intentos será la probabilidad?: "))
    main(tamano_mano, intentos)

    # mano = obtener_mano(barajas, 5)
    # barajas = crear_baraja()

    # print(mano)
    # print(barajas)
    # print(len(barajas))

todas las cartas del mismo color al correr la simulación 100mil veces, la probabilidad es del 0,0019 es decir 0,19%

Tardé un poco (como 6 hrs) pero al fin lo logré; las probabilidades de todas las manos de póker:

Mi código lo pueden ver en mi repositorio de github.

Reto de la probabilidad de una escalera:

# Simulation decks
import random
import collections

DECKS = ['spades', 'hearts', 'diamonds', 'clubs']
VALUES = [i for i in range(1,14)]

def create_deck():
    """This function create a deck"""
    decks = []
    for deck in DECKS:
        for value in VALUES:
            decks.append((deck, value))
    return decks

def get_hand(decks, len_hand):
    """Obtain a random hand"""
    hand = random.sample(decks, len_hand)

    return hand

def checkConsecutive(l):
    """Check if is a straight"""
    return sorted(l) == list(range(min(l), max(l)+1)) 

def main(len_hand, times):
    """get the probabilities of the hands"""
    decks = create_deck()

    hands = []
    for _ in range(times):
        hand = get_hand(decks, len_hand)
        hands.append(hand)
    
    pairs = 0
    three_of_a_kind = 0
    straight = 0
    for hand in hands:
        values = [card[1] for card in hand]
        counter = dict(collections.Counter(values))
        for val in counter.values():
            if val == 2:
                pairs += 1
                break
            elif val == 3:
                three_of_a_kind += 1
                break
        if checkConsecutive(values):
            straight += 1

    pair_probability = pairs / times
    print(f'The probability of get a pair in one hand of {len_hand} cards is {pair_probability}')
    
    three_probability = three_of_a_kind / times
    print(f'The probability of get a three of a kind in one hand of {len_hand} cards is {three_probability}')

    straight_probability = straight / times
    print(f'The probability of get a straight in one hand of {len_hand} cards is {straight_probability}')

if __name__ == '__main__':
    try:
        len_hand = int(input('How many cards will the hand have? '))
        times = int(input("how many times do you want to run the simulation? "))

        main(len_hand, times)
    except KeyboardInterrupt as ki:
        print("\n This process has been canceled. Retry.")

Resultado

How many cards will the hand have? 5
how many times do you want to run the simulation? 20000
The probability of get a pair in one hand of 5 cards is 0.47165
The probability of get a three of a kind in one hand of 5 cards is 0.0225
The probability of get a straight in one hand of 5 cards is 0.0039

Aca esta la solucion al reto, Codigo:

Output:

La probabilidad de obtener una corrida en una mano de 5 cartas con 1000 intentos es de 0.0044

import random
import collections

PALOS = ['espada', 'corazones', 'diamante', 'trebol']
VALORES = ['as'] + [str(i) for i in range(2, 11)] + ['jota', 'reina', 'rey']

def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            barajas.append((palo, valor))
    
    return barajas

def obtener_mano(barajas, tamano_mano):
    # la fun random.sample obtiene una muestra unica de un conjunto
    mano = random.sample(barajas, tamano_mano)

    return mano

def main(tamano_mano, intentos):
    barajas = crear_baraja()
    
    manos = []
    for _ in range(intentos):
         mano = obtener_mano(barajas, tamano_mano)
         manos.append(mano)

    pares = 0
    trios = 0
    corrida = 0
    orden = [i for i in range(5)]
    for mano in manos:
        valores = []        
        for carta in mano:
            valores.append(carta[1])
        
        counter = dict(collections.Counter(valores))
        for val in counter.values():
            if val == 2:
                pares += 1
                break
        
        for val in counter.values():
            if val == 3:
                trios += 1
                break
        
        indice_cartas = []
        for val in valores:
            indice_cartas.append(VALORES.index(val))
        
        indice_cartas.sort()
        validacion_corrida = []
        for i in indice_cartas:
            validacion_corrida.append(i - indice_cartas[0])
        
        if validacion_corrida == orden:
            corrida += 1      

    
    probabilidad_par =  pares / intentos
    probabilidad_trio = trios / intentos
    probabilidad_corrida = corrida / intentos
    print(f'La probabilidad de encontrar un par en una mano de {tamano_mano} cartas es {probabilidad_par}')
    print(f'La probabilidad de encontrar un trio en una mano de {tamano_mano} cartas es {probabilidad_trio}')
    print(f'La probabilidad de encontrar una corrida en una mano de {tamano_mano} cartas es {probabilidad_corrida}')




if __name__ == '__main__':
    tamano_mano = int(input('De cuantas cartas es la mano: '))
    intentos = int(input('Cuantos intentos para calcular la probabilidad: '))
    
    main(tamano_mano, intentos)

La probabilidad es muy muy baja según mi algoritmo de que las 5 cartas sean una corrida :0
Con un solo palo existe una probabilidad de 0.4%

import random
import collections

PALOS = ['espada', 'corazon', 'rombo', 'trebol']
VALORES = ['1', '2', '3', '4', '5', '6', '7', '8', '9','10', '11', '12', '13']

def ordenamiento_por_mezcla(lista):
    if len(lista) > 1:
        medio = len(lista) // 2
        izquierda = lista[:medio]
        derecha = lista[medio:]

        ordenamiento_por_mezcla(izquierda)
        ordenamiento_por_mezcla(derecha)

        i = 0
        j = 0
        k = 0

        while i < len(izquierda) and j < len(derecha):
            if izquierda[i] < derecha[j]:
                lista[k] = izquierda[i]
                i += 1
            else:
                lista[k] = derecha[j]
                j += 1

            k += 1

        while i < len(izquierda):
            lista[k] = izquierda[i]
            i += 1
            k +=1

        while j < len(derecha):
            lista[k] = derecha[j]
            j += 1
            k += 1

    return lista

def crear_baraja():
	barajas = []
	for palo in PALOS:
		for valor in VALORES:
			barajas.append((palo, valor))

	return barajas

def obtener_mano(barajas, tamano_mano):
	mano = random.sample(barajas, tamano_mano)

	print(mano)

	return mano

def main(tamano_mano, intentos):
	barajas = crear_baraja()

	manos = []
	for _ in range(intentos):
		mano = obtener_mano(barajas, tamano_mano)

		manos.append(mano)

	corridas = 0
	puntero = mano[0]
	for mano in manos:
		counter = 0
		valores = []

		for i in range(5):
			counter += 1
			palo = mano[i]
			valores.append(palo[1])
			if palo[0] != puntero[0]:
				break

		if counter == 5:
			lista_ord = ordenamiento_por_mezcla(valores)

			band = 0
			for j in range(4):
				valor = lista_ord[j]
				if (int(valor)+1) != int(lista_ord[j+1]):
					band = 1
					break

			if band == 0:
				corridas += 1

	probabilidad_corrida = corridas / intentos
	print(f'La probabilidad de obtener una corrida en una mano {tamano_mano} barajas es {probabilidad_corrida}')

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)

A resolver el ejercicio

Para los que no sepan de poker como yo.

Flor corrida (Escalera color) cinco cartas del mismo palo en secuencia, tal como 98765 de corazones. El As puede jugarse como carta baja para hacer una flor corrida (escalera color) 5432A, la flor corrida (escalera color) más baja.

Una tercia es un trio no?

Por si alguien quiere ahondar un poco mas en el uso de la ** función random.sample()** les dejo este link:
https://pynative.com/python-random-sample/
Explican bastante bien que puedes hacer con esa función al manipular listas y diccionarios.

  • Dejo mi código con comentarios. Estos son mir resultados:

Cuantas cartas quieres en tu mano? 5
Cuantas simulaciones deseas? 1000000
La probabilidad de encontrar al menos un par en una mano de 5 es de 47.2414 %
La probabilidad de encontrar al menos un tercio en una mano de 5 es de 2.2340999999999998 %
La probabilidad de encontrar al menos un doble par en una mano de 5 es de 4.7902000000000005 %
La probabilidad de encontrar al menos un full house par en una mano de 5 es de 0.1419 %
La probabilidad de encontrar todas las cartas de igual color en una mano 5 es de 0.20010000000000003 %
La probabilidad de encontrar una escalera en una mano de 5 es de 0.3467 %
La probabilidad de encontrar una escalera de color en una mano de 5 es de 0.0015999999999999999 %
La probabilidad de encontrar una escalera real en una mano de 5 es de 9.999999999999999e-05 %

import random
import collections
PALOS = ['espada','corazon','rombo','trebol']
VALORES = ['1','2','3','4','5','6','7','8','9','10','11','12','13']
#Crea el mazo de cartas
def crear_barajas():
    baraja = []
    for palo in PALOS:
        for valor in VALORES:
            baraja.append((palo,valor))
    return baraja

#Crea las manos
def obtener_mano(baraja, tamano_mano):
    #Obtiene una carta al azar sin repetición
    #Osea nunca selecciona dos veces la misma carta
    #Requiere un iterable (baraja)y cuantas muestras tomara (cartas)
    mano = random.sample(baraja, tamano_mano)
    return mano

#Verifica el par y el trio
def pares_trios_dobles(manos):
    #Contabilizar en cuantas manos salio un par y un trio
    pares = 0
    tercio = 0
    doble_par = 0
    full_house = 0
    for mano in manos:
        valores = []
        for carta in mano:
            #Separamos y guardamos los valores de las cartas
            #Sin revisar el palo al que pertenecen
            valores.append(carta[1])
            
            #collection.Counter(iterable) cuenta cuantos valores
            #del mismos tipo se encuentran en un iterable, retornando
            #el nombre del valor key (as, 2, 3 ....) y cuantas veces a sido
            # mensionado o encontrado value, por esto se debe almacenar en un 
            # diccionario 
            counter = dict(collections.Counter(valores))
        #Las banderas sirver para verificar si dos o mas condiciones se han cumplido en una mano
        bandera1 = 0
        bandera2 = 0
        bandera3 = 0
        for valor in counter.values():
            #Solo queremos ver los casos donde encontramos solo un par
            #ignoramos si hay dos o mas cartas repetidas en la mano
            if valor == 2 and bandera1 == 0:
                pares += 1
                bandera1 += 1
            #Verificamos si hay al menos un trio   
            if valor == 3 and bandera2 == 0:
                tercio += 1
                bandera2 += 1
            #Si tenemos al menos dos pares
            if valor == 2 and bandera3 <= 2:                
                bandera3 += 1
                #Si encuentro un segundo par aumento el contador de dobles
                if bandera3 == 2:
                    doble_par += 1
            #Si tengo en la mano un par y un trio aumento el contador full house
            if bandera1 == 1 and bandera2 == 1:
                full_house += 1 
    print(f'La probabilidad de encontrar al menos un par en una mano de {tamano_mano} es de {pares/intentos*100} %')
    print(f'La probabilidad de encontrar al menos un tercio en una mano de {tamano_mano} es de {tercio/intentos*100} %')
    print(f'La probabilidad de encontrar al menos un doble par en una mano de {tamano_mano} es de {doble_par/intentos*100} %')
    print(f'La probabilidad de encontrar al menos un full house par en una mano de {tamano_mano} es de {full_house/intentos*100} %')

#Verificar escalera
def escalera_escalera_color(manos):
    escaleras = 0
    escalera_color = 0    
    escalera_real = 0 
    igual_color = 0
    for mano in manos:
        #Guardara solo el valor de la carta
        #ignorando el palo
        valores = []
        color = []
        cont = 0
        cont2 = 0
        for carta in mano:
            valores.append(int(carta[1]))
            color.append(carta[0])
            #Ordenamos la mano
            valores.sort(reverse=True)
        for valor in range(len(valores)-1):
            #Verifica si son consecutivas los valores de las cartas de la mano
            if (valores[valor] - valores[valor+1]) == 1:
                cont += 1
            #Verifica si son del mismo color las cartas de la mano
            if color[valor] == color[valor +1]:
                cont2 += 1
            #Si las cinco son de mismo color aumento el contador igual_color
            if cont2 == (len(valores) - 1):
                igual_color += 1
            #Si las cinco cartas son consecutivas cuento una nueva esclera
            if cont == (len(valores)-1):
                escaleras += 1      
            #Si las cinco cartas son consecutivas y del mismo color
            #cuento una nueva escalera de color
            if cont == (len(valores)-1) and cont2 == (len(valores)-1):
                escalera_color += 1
            #Si las cartas ademas de ser una escalera de color inician y 
            #terminan en K, Q, J, 10 y 9 sumare una escalera real
            if cont == (len(valores)-1) and cont2 == (len(valores)-1) and valores[0]==13 and valores[len(valores)-1]==9:
                escalera_real += 1

    print(f'La probabilidad de encontrar todas las cartas de igual color en una mano {tamano_mano} es de {igual_color/len(manos)*100} %')
    print(f'La probabilidad de encontrar una escalera en una mano de {tamano_mano} es de {escaleras/len(manos)*100} %')
    print(f'La probabilidad de encontrar una escalera de color en una mano de {tamano_mano} es de {escalera_color/len(manos)*100} %')  
    print(f'La probabilidad de encontrar una escalera real en una mano de {tamano_mano} es de {escalera_real/len(manos)*100} %')  

def main(tamano_mano, intentos):
    baraja = crear_barajas()
    #Guarda las manos que obtengamos 
    #Conjuntos de cartas 
    manos = []
    for _ in range(intentos):
        #Grupo de cartas obtenidos
        mano = obtener_mano(baraja, tamano_mano)
        #Grupos totales de cartas conseguidos
        manos.append(mano)
    
    #Funcion para contar pares y trios en una mano
    pares_trios_dobles(manos)
    #Funcion para hacer escalera de 5 cartas consecutivas
    #todas las cartas del mismo color
    # escaleras del mismo color
    # escalera real 
    escalera_escalera_color(manos)
    
if __name__ == '__main__':
    tamano_mano = int(input('Cuantas cartas quieres en tu mano? '))
    intentos = int(input('Cuantas simulaciones deseas? '))
    main(tamano_mano, intentos)```

Me costó trabajo pero aquí está:



import random
import collections

PALOS = ['espada', 'corazon', 'rombo', 'trebol']
#VALORES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey']
VALORES = list(range(1,14))


def crear_baraja():
    barajas = []
    for palo in PALOS:
        for valor in VALORES:
            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 _ in range(intentos):
        mano = obtener_mano(barajas, tamano_mano)
        manos.append(mano)
    
    comprobacion_escalera = 0
    for mano in manos:
        valores = []
        escalera = 0
        for carta in mano:
            valores.append(carta[1])
            valores.sort()
            
        #print(valores)
        
        for i in range(0,tamano_mano-1):
            if valores[i+1] == valores[i]+1:
                escalera += 1
                
                if escalera == tamano_mano-1:
                    comprobacion_escalera += 1
                    break
                
            
        #print(comprobacion_escalera)   
            
            
    probabilidad_par = comprobacion_escalera / intentos
    print(f'La probabilidad de obtener una escalera en una mano de {tamano_mano} cartas es {probabilidad_par}')
     
        
        

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)

Por fin puedo seguir con las clases. Aunque si me gustaría saber si mi código es eficiente hablando en términos de complejidad algorítmica.

Hice un algoritmo para blackack
calcula la probabilidad de que nos salga 21 en el primer intento de tomar un unumero de cartas al azar

y claro nos dice cual fue la mano por la cual sumamos el 21, asi creo saber que esta bueno jajaj

import random
import collections

TYPES = ['espada', 'corazon', 'rombo', 'trebol']
VALUES = ['as', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'jota', 'reina', 'rey']


def make_cards():
    cards = []
    for types in TYPES:
        for values in VALUES:
            cards.append((types, values))

    return cards

def make_my_hand(cards, hand_size):
    # random choice pero sin repetir 
    hand = random.sample(cards, hand_size)
    return hand

def main(cards_in_hand, try_number):
    cards = make_cards()
    hands = []
    for _ in range(try_number):
        hand = make_my_hand(cards, cards_in_hand)
        hands.append(hand)


  
 
    twenty_ones = 0
    WIINER_HAND = []
    counter_hand_laps = 0
    TOTAL = 0
    IFAS = False 
    counter = 0
    for hand in hands:
        for card in hand:

            counter +=1 
        
            counter_hand_laps += 1
            # print(counter_hand_laps)
            if card[1] == 'espada' or card[1] == 'reina' or card[1] == 'rey' or card[1] == '10'  or card[1] == 'jota':
                TOTAL = 10
                # print('capturamos un 10')
                # print(card)
            elif card[1] == '2':
                TOTAL  += 2
            elif card[1] == '3':
                TOTAL   += 3
            elif card[1] == '4':
                TOTAL   += 4
            elif card[1] == '5':
                TOTAL  += 5
            elif card[1] == '6':
                TOTAL   += 6
            elif card[1] == '7':
                TOTAL   += 7
            elif card[1] == '8':
                TOTAL   += 8
            elif card[1] == '9':
                TOTAL  += 9

            if card[1] == 'as':
                IFAS = True
            
            # print(TOTAL)
                        
            # si ya recorrimos toda la mano
            if counter_hand_laps == cards_in_hand:
                # print('ya recorrimos toda la mano')
                # si tenemos un as
                if IFAS == True:
                    # y un 10 
                    if TOTAL == 10:
                        # tenemos 21
                        twenty_ones += 1
                        print('hand 0')
                        print(hand)
                        # WIINER_HAND = WIINER_HAND.append(card)
                    # y un 20 
                    if TOTAL == 20:
                        # tenemos 21
                        twenty_ones += 1
                        print('hand 1')
                        print(hand)
                        # WIINER_HAND = WIINER_HAND.append(card)

                #si tenemos 21    
                elif TOTAL == 21:
                    # tenemos 21 jejeje  
                    twenty_ones += 1
                    print('hand 2')
                    print(hand)
                    # WIINER_HAND = WIINER_HAND.append(card)
                elif TOTAL != 21: 
                    # si no tenemos 21 y ya recorrimos toda la mano entonces reiniciamos los valores 
                    counter_hand_laps = 0
                    TOTAL = 0
                    IFAS = False
         
     
            
    probabilidad = twenty_ones / try_number
    probabilidad = probabilidad * 100
    print(f'La probabilidad de obtener un 21 en una mano de {cards_in_hand} cards al azar en el primer intento es de {probabilidad}')

if __name__ == "__main__":
    cards_in_hand = int(input('De cuantas barajas sera la mano: '))
    try_number = int(input('Cuantos intentos para calcular la probabilidad: '))

    main(cards_in_hand, try_number)

cualquier mejora que le puedan hacer o como reducir la complejidad algoritmica sera de gra ayuda

Gracias por esta nueva perspectiva de ver desde el lado de posibilidades, fantástico.

Hice una función para determinar escaleras en una mano de estrictamente 5 barajas! para ello modifiqué un poco la constante de VALORES.

VALORES = {
  1: 'as',
  2: 'two',
  3: 'three',
  4: 'four',
  5: 'five',
  6: 'six',
  7: 'seven',
  8: 'eight',
  9: 'nine',
  10: 'ten',
  11: 'jack',
  12: 'queen',
  13: 'king'}

def escalera(mano):
  """Retorna True cuando hay escalera False cuando no la hay, recibe solo manos de 5 barajas."""
  valores = []
  for carta in mano:
    valores.append(carta[0])

  # Si hay valores que se repiten directamente no hay escalera
  counter = dict(collections.Counter(valores))
  for val in counter.values():
    if val > 1:
      return False

  # Si no hay valores que se repiten y el maximo valor de la mano menos el minimo valor es igual a 4 significa que hay escalera.
  if max(valores) - min(valores) == 4:
    return True
  
  # Ultimo caso, para chequear la escalera del 10 al as.
  if (max(valores) == 13) and (min(valores) == 1):
    valores_ordenados = sorted(valores)
    if valores_ordenados[1] == 10:
      return True
    else:
      return False

Probabilidad para sacar una escalera en una sola mano de 5 cartas
Cuantas cartas tendras en la mano: 5
Cuentas veces sera ejecutada esta simulacion: 1000000
La probabilidad de encontrar una escalera en una mano de 5 cartas es 0.3535 %.

escalera = 0
    for mano in manos:
        valores = []
        for carta in mano:
            valores.append(carta[1])

        valores = [int(i) for i in valores]
        valores.sort()
        if valores[0] + 4 == valores[4] and valores[1] + 3 == valores[4] and valores[2] + 2 == valores[4] and valores[
            3] + 1 == valores[4]:
            escalera += 1