-1

After testing pokers hands x amount of times, I need to print a table with the title of the hand (full house, flush, etc.), the number of times each of them occurred, the percentage of times they occurred, expected percentage, and difference between the two. It won't let me run it with more than 2 iterations.

Here is what I have:

def is_pair(hand):
    Yes = 0
    for card in hand:
        count = 0
        for i in hand:
            if (card['value']) == (i['value']):
                count += 1
        if count == 2:
            Yes = 1
    if Yes == 0:
        return False
    else:
        if is_full_house(hand) is True:
            return False
        elif is_2_pair(hand) is True:
            return False
        elif is_3_of_a_kind(hand) is True:
            return False
        elif is_4_of_a_kind(hand) is True:
            return False
        else:
            return True

def is_2_pair(hand):
    Yes = 0
    for card in hand:
        count = 0
        for i in hand:
            if card['value'] == i['value']:
                count += 1
        if count == 2:
            Yes += 1
    if Yes == 4:
        if is_4_of_a_kind(hand) is True:
            return False
        elif is_full_house(hand) is True:
            return False
        else:
            return True
    else:
        return False

def is_3_of_a_kind(hand):
    Yes = 0
    for card in hand:
        count = 0
        for i in hand:
            if card['value'] == i['value']:
                count += 1
        if count == 3:
            Yes = 1
    if Yes == 0:
        return False
    else:
        if is_full_house(hand) is True:
            return False
        else:
            return True

def is_4_of_a_kind(hand):
    Yes = 0
    for card in hand:
        count = 0
        for i in hand:
            if card['value'] == i['value']:
                count += 1
        if count == 4:
            Yes = 1
    if Yes == 0:
        return False
    else:
        return True

def is_full_house(hand):
    Yes = 0
    if is_3_of_a_kind(hand) is True:
        Yes += 1
    else:
        return False
    if is_pair(hand) is True:
        Yes += 1 
    else:
        return False
    if Yes == 2:
        return True
    else:
        return False

def is_flush(hand):
    Yes = 0
    for card in hand:
        count = 0
        for i in hand:
            if card['suit'] == i['suit']:
                count += 1
        if count == 5:
            Yes = 1
    if Yes == 0:
        return False
    else:
        return True

def is_straight(hand):
    list = []
    for card in hand:
        list.append(card['value'])
        list.sort()
    if is_pair(hand) is True:
        return False
    elif is_2_pair(hand) is True:
        return False
    elif is_3_of_a_kind(hand) is True:
        return False
    elif is_4_of_a_kind(hand) is True:
        return False
    elif is_full_house(hand) is True:
        return False
    elif list[4] - list [0] == 4:
        return True
    else:
        return False

def is_high_card(hand):
    if (is_pair(hand) is False) and (is_2_pair(hand) is False) and (is_3_of_a_kind(hand) is False) and (is_4_of_a_kind(hand) is False) and (is_flush(hand) is False) and (is_full_house(hand) is False) and (is_straight(hand) is False) and (is_straight_flush(hand) is False):
        return True
    else:
        return False

def is_straight_flush(hand):
    if (is_straight(hand) is True) and (is_flush(hand) is True):
        return True
    else:
        return False

def main():
    deck = build_deck()
    shuffle(deck)
    hand = deck[:5]
    return hand

def tests():
    hand = main()
    if is_straight_flush(hand) is True:
        return('Straight flush')
    elif is_4_of_a_kind(hand) is True:
        return('Four of a kind')
    elif is_full_house(hand) is True:
        return('Full house')
    elif is_flush(hand) is True:
        return('Flush')
    elif is_straight(hand) is True:
        return('Straight')
    elif is_3_of_a_kind(hand) is True:
        return('Three of a kind')
    elif is_2_pair(hand) is True:
        return('Two pairs')
    elif is_pair(hand) is True:
        return('One pair')
    elif is_high_card(hand) is True:
        return('High card')

def main2():
    iterations = int(input("How many hands would you like to test? "))
    hands = ['Straight flush', 'Four of a kind', 'Full house', 'Flush', 'Straight', 'Three of a kind', 'Two pair', 'One pair', 'High card']
    sf_expected = round(40/2598960*100, 4)
    fok_expected = round(624/2598960*100, 4)
    fh_expected = round(3744/2598960*100, 4)
    f_expected = round(5108/2598960*100, 4)
    s_expected = round(10200/2598960*100, 4)
    tok_expected = round(54912/2598960*100, 4)
    tp_expected = round(123552/2598960*100, 4)
    op_expected = round(1098240/2598960*100, 4)
    hc_expected = round(1302540/2598960*100, 4)
    sf_freq = 0
    fok_freq = 0
    fh_freq = 0
    f_freq = 0
    s_freq = 0
    tok_freq = 0
    tp_freq = 0
    op_freq = 0
    hc_freq = 0
    for i in range(iterations):
        tests()
        if (tests() == 'Straight flush'):
            sf_freq += 1
        if (tests() == 'Four of a kind'):
            fok_freq += 1
        if (tests() == 'Full house'):
            fh_freq += 1
        if (tests() == 'Flush'):
            f_freq += 1
        if (tests() == 'Straight'):
            s_freq += 1
        if (tests() == 'Three of a kind'):
            tok_freq += 1
        if (tests() == 'Two pair'):
            tp_freq += 1
        if (tests() == 'One pair'):
            op_freq += 1
        if (tests() == 'High card'):
            hc_freq += 1
    occurences = [sf_freq, fok_freq, fh_freq, f_freq, s_freq, tok_freq, tp_freq, op_freq, hc_freq]
    expected = [sf_expected, fok_expected, fh_expected, f_expected, s_expected, tok_expected, tp_expected, op_expected, hc_expected]
    percent = [sf_freq/iterations * 100, fok_freq/iterations * 100, fh_freq/iterations * 100, f_freq/iterations * 100, s_freq/iterations * 100, tok_freq/iterations * 100, tp_freq/iterations * 100, op_freq/iterations * 100, hc_freq/iterations * 100]
    difference = [sf_freq/iterations * 100 - sf_expected, fok_freq/iterations * 100 - fok_expected, fh_freq/iterations * 100 - fh_expected, f_freq/iterations * 100 - f_expected, s_freq/iterations * 100 - s_expected, tok_freq/iterations * 100 - tok_expected, tp_freq/iterations * 100 - tp_expected, op_freq/iterations * 100 - op_expected, hc_freq/iterations * 100 - hc_expected]
    print("{:<15} {:<15} {:<15} {:<15} {:>15}".format('Hand', 'Occurences','Percent', 'Expected', 'Difference'))
    all = [['Straight flush', sf_freq, sf_freq/iterations * 100, sf_expected, sf_freq/iterations * 100 - sf_expected],
            ['Four of a kind', fok_freq, fok_freq/iterations * 100, fok_expected, fok_freq/iterations * 100 - fok_expected],
            ['Full house', fh_freq, fh_freq/iterations * 100, fh_expected, fh_freq/iterations * 100 - fh_expected],
            ['Flush', f_freq, f_freq/iterations * 100, f_expected, f_freq/iterations * 100 - f_expected],
            ['Straight', s_freq, s_freq/iterations * 100, s_expected, s_freq/iterations * 100 - s_expected],
            ['Three of a kind', tok_freq, tok_freq/iterations * 100, tok_expected, tok_freq/iterations * 100 - tok_expected],
            ['Two pair', tp_freq, tp_freq/iterations * 100, tp_expected, tp_freq/iterations * 100 - tp_expected],
            ['One pair', op_freq, op_freq/iterations * 100, op_expected, op_freq/iterations * 100 - op_expected],
            ['High card', hc_freq, hc_freq/iterations * 100, hc_expected, hc_freq/iterations * 100 - hc_expected]]
    for list in all:
        hands, occurences, percent, expected, difference = list
        print("{:<15} {:<15} {:<15} {:<15} {:>15}".format(hands, occurences, percent, expected, difference))

main2()
newbie
  • 21
  • 5
  • Your code seems to have some `print()` statements. Does your code not get as far as executing those or do they not print what you want? – quamrana Apr 15 '22 at 17:39
  • Do you realize that calling `int()` on the results of over half of those calculations will give you a zero? – MattDMo Apr 15 '22 at 17:46

1 Answers1

0

It's a little unclear why you aren't getting any output, which seems to be the implication of your question. Is your code raising an exception?

It looks to me like the problem is with results. This appears to be a standard Python list (containing a collection of integers). Calling something like results/iterations would normally result in something like TypeError: unsupported operand type(s) for /: 'list' and 'int'.

Lists are not intended to support operations that apply to all their elements, but it's also unclear that's what you intended to achieve with this. Your format string specifies that results/iterations * 100 should be rendered in a space 10 characters wide and centered.

I believe you perhaps wanted to iterate through the individual values of hands, results, and expected, producing a set of rows to form a table. In that case I propose the following in place of your second print statement:

for hand, freq, expectation in zip(hands, results, expected):

    percent = 100 * freq / iterations

    print(f"{hand:^10}{freq:^10}{percent:^10}{expectation:^10}{percent-expectation:^10}")

I have used the somewhat friendlier f-string formatting, but if you have python <3.6 feel free to revert.


In general, the pandas data analysis library is a good fit for this kind of problem, since you can simply put your data in a pandas DataFrame and print it. However I appreciate that you may want to do this in base Python.


While I'm at it, I fear you have another error. You haven't told us what tests() does, but it looks like instead of calling it once per iteration and processing the result you call it many times.

Let me help you tidy your code and make it more maintainable, fixing this issue in the process.

    hands = ['Straight flush', 'Four of a kind', 'Full house', 'Flush', 'Straight', 'Three of a kind', 'Two pair', 'One pair', 'High card']
    results = {hand: 0 for hand in hands}

    denom = 2598960 / 100
    expected = [int(40/denom), int(624/denom), int(3744/denom), int(5108/2598960*100), int(10200/denom), int(54912/denom), int(123552/denom), int(1098240/denom), int(1302540/denom)]
    
    for i in range(iterations):
        hand = tests()
        results[hand] += 1
        

By using a dictionary to store the results and using the hand name as the key to look up the result for that hand we improve the code.

You would then use results.values() to retrieve the list of results you had before.

I have also put your repeated code into a variable. If you ever had to change it, you now only have to change it in one place, making mistakes much less likely.

Paddy Alton
  • 1,855
  • 1
  • 7
  • 11
  • Thank you so much! I got it to run and give me the desired output, but it won't run if I put in more than 9 for iterations. Is there a simple way to fix this? – newbie Apr 15 '22 at 18:48
  • That depends on what you mean when you say that it won't run. Are you getting an error/exception of some kind? It is always helpful to provide the details of any exceptions you encounter - they are there to help you fix code issues. – Paddy Alton Apr 15 '22 at 18:59
  • Yes, it gives me the error "RecursionError: maximum recursion depth exceeded in comparison" and before that, it says " return None if event == 'call' else NO_FTRACE" – newbie Apr 15 '22 at 19:10
  • Ah! Okay, I am sure that is a problem with your `tests()` function that you haven't told us much about. The 'before' bit is the line that raises the exception, but in this case the key problem is that there is some recursive element to the function (that is, you have a function that calls itself somewhere in there!). Are you confident that code is behaving as it ought to? – Paddy Alton Apr 15 '22 at 19:16
  • See also this answer, which will explain the recursion issue quite clearly: https://stackoverflow.com/a/3323013/9044370 – Paddy Alton Apr 15 '22 at 19:18
  • I edited my question to include more of the code. I have tested the tests() function many times and I am pretty confident it works the way it's supposed to. – newbie Apr 15 '22 at 19:27
  • Oh, I see the issue. Look at `is_pair` and `is_full_house` (for example). You'll notice that *sometimes* they call each other (the element of randomness means it won't always happen!). You're hitting the recursion error when you end up in an infinite loop (A calls B calls A calls...). I'm afraid you have a serious case of 'spaghetti code' (a description we use for very convoluted logical flow). The problem with such code is that you're vulnerable to issues like this, as they become hard to spot. I recommend trying to simplify if possible. – Paddy Alton Apr 15 '22 at 19:43
  • Thank you so much for all your help, Paddy. I am certainly on the right track now. – newbie Apr 15 '22 at 20:00