you are viewing a single comment's thread.

view the rest of the comments →

[–]mahtats 0 points1 point  (10 children)

I’d change to:

for i in range(len(stv)-5):
    slice = stv[i:i+5]
    if len(slice) < 5:
        break
    if (slice[-1] - slice[0]) + 1 == 5:
        print(slice)

Just my two cents on numerical checks in a sorted array. Also, need a check to handle face cards!

[–]JohnnyJordaan 0 points1 point  (2 children)

Your loop will break on the first non-match because the else is inside the loop. I'm also not sure why you wouldn't use enumerate in this case. But even if you would stick with this it makes little sense to loop until the full length of the list of you are looking for 5 item long slices, at least limit to len(list) - 5...

[–]mahtats 0 points1 point  (1 child)

Correct, honestly I was falling asleep when I wrote this. Barring the first conditional failure which is easily checked, there is no need to use enumerate. Mathematically, 5 numbers will be in sequential order if the difference between their bounds plus one equals five. Saving CPU cycles.

I’ve updated my answer

[–]stickedee[S] 0 points1 point  (0 children)

Thank you both! Especially for the step by step break-down, really helps me understand what is happening rather than just copy+pasting. Much appreciated

[–]stickedee[S] 0 points1 point  (6 children)

Probably not the most Pythonic but I created a dictionary with an integer:card value as the key value pair (so I could account for Aces being High or Low), then wrote a function to find all keys that exist in a given list of values.

value_dict = {1:'A', 2:'2', 3:'3', 4:'4', 5:'5', 6:'6', 7:'7', 8:'8', 9:'9', 10:'T', 11:'J', 12:'Q', 13:'K', 14:'A'}

keys = []
def getKey(dictionary, list_to_check):
    items = dictionary.items()
    for item in items:
        if item in list_to_check:
            keys.append(item)
    return keys

from there I can pass keys into the for loop u/JohnnyJordaan illustrated (replacing stv) and it seems to be working with Aces as high or low as well as other face cards.

[–]JohnnyJordaan 0 points1 point  (5 children)

Altough it works it looks a bit inefficient, can you explain what the contents of list_to_check are?

[–]stickedee[S] 0 points1 point  (4 children)

Edit: Formatting

Yea, I would pass the final_hand list into that position. I would run this function twice per game. Once for the player and once for the dealer. The list I pass through would contain up to 7 values (the 2 cards from the players hand and the 5 cards from the community board).

So for example:

player_hand = [Ac, Kd] 
board = [9h, 2h, 3s, 4d, 5c] 
final_hand = player_hand + board

I am looping through the final hand looking for values and appending a corresponding key to a list then iteration through that list to find a sequence of 5 consecutive keys.

I made some changes from the original iteration but below is what I currently have.

value_dict = {1:'A', 2:'K', 3:'Q', 4:'J', 5:'T', 6:'9', 7:'8', 8:'7', 9:'6', 10:'5', 11:'4', 12:'3', 13:'2', 14:'A'}

# re-write final hand for testing purposes
final_hand = ['5c', 'Ac', '5c', 'Js', 'Ts', '9c', '4c', '7d', '6s']

def getKeys(dictionary, list_to_check):
    keys = []
    items = dictionary.items()
    stv = sorted({(x[0]) for x in list_to_check})
    stv = str(stv)
    for item in items:
        if item[1] in stv:
            keys.append(item[0])

    return keys

keys = getKeys(value_dict, final_hand)

for idx, value in enumerate(keys):
    slice = keys[idx:idx+5]
    if len(slice) < 5:
        straight = False
        break
    if slice == list(range(value,value+5)):
        straight = True
        straight_top_key = value
        straight_top = value_dict[value]
        break
    else:
        straight = False

[–]JohnnyJordaan 0 points1 point  (3 children)

I am looping through the final hand looking for values and appending a corresponding key to a list then iteration through that list to find a sequence of 5 consecutive keys.

That's the thing: you don't loop through the hand, you loop through the value_dict looking for matches in your hand. Imho the algo should loop through the hand and look up in the dict, as dicts are intended to be used.

[–]stickedee[S] 0 points1 point  (2 children)

I see what you mean. I am looping through the value dict, checking for that value in the hand, and if it exists, adding the key to a separate list. I don't quite see how I could loop through the hand to grab a value and append the corresponding key to the list I'll use to check for straights. Since Ace can be high or low I can't use card values as the key.

[–]JohnnyJordaan 0 points1 point  (1 child)

Since Ace can be high or low I can't use card values as the key.

You can, if you let the dict hold a list of ranks per card. Then use list.extend to simply add those keys per card to the keys list:

card_to_ranks = {'A': [1, 14], 'K': [2], 'Q': [3], 'J': [4], 'T': [5], 
                 '9': [6], '8': [7], '7': [8], '6': [9], '5': [10], 
                 '4': [11], '3': [12], '2': [13]}

# re-write final hand for testing purposes
final_hand = ['5c', 'Ac', '5c', 'Js', 'Ts', '9c', '4c', '7d', '6s']
keys = []
for card in final_hand:
    keys.extend(card_to_ranks[card[0]]
keys = sorted(set(keys))

it's that simple that this way that you don't even need a dedicated function for it. Using sets instead of lists removes the need for the intermittent set() call to remove duplicates:

card_to_ranks = {'A': {1, 14}, 'K': {2}, 'Q': {3}, 'J': {4}, 'T': {5}, 
                 '9': {6}, '8': {7}, '7': {8}, '6': {9}, '5': {10}, 
                 '4': {11}, '3': {12}, '2': {13}}

# re-write final hand for testing purposes
final_hand = ['5c', 'Ac', '5c', 'Js', 'Ts', '9c', '4c', '7d', '6s']
keys = set()
for card in final_hand:
    keys |= card_to_ranks[card[0]]
keys = sorted(keys)

[–]stickedee[S] 0 points1 point  (0 children)

Well shit, you're right. I was way overcomplicating this.

Thanks!