-4

In python I have a score tracker of a poker hand.

Possible card ranks:

A23456789TJQK

Straights of 3 or more cards score 1 per card. Example straight of 4 cards gives you 4 points.

So I have a score:

score = 0

A sorted list of strings (so I don't have to worry about cards at the end of the list having a straight with the beginning) representing the card ranks of my particular hand:

L4
['6', '8', '8', '9', 'T']
# Note: 8, 9, T is a straight. So I want to add 3 to score

But how can I determine if I have a straight?

What I've tried so far:

I tried converting the strings into integers, but then what do I do with the T, J, K, Q, and A? They aren't numbers.

Using strings I get an error:

for i in range(len(L4) - 1):
   if(L4[i] is L4[i + 1] + 1):
      sC = sC + 1
if(sC >= 3):
   score += sC


L4
['6', '8', '8', '9', 'T']
Traceback (most recent call last):
  File "myFile.py", line 66, in <module>
    if(L4[i] is L4[i + 1] + 1):
TypeError: must be str, not int

Should I convert them to ints or should I try another way? Thanks for help in advance.

Coder117
  • 801
  • 2
  • 9
  • 22
  • 1
    Use a dictionary and translate T, J, K, Q, A into numbers. – Mr. T May 24 '18 at 18:25
  • your question is not clear `'6','7','8','9' == 1 straight of 4 or 2 straights of 3`? because i get more points counting it as 2 straights of 3 – Joran Beasley May 24 '18 at 18:29
  • That's one of many problems of using strings to represent cards. Use numbers from the ground up, and only convert to strings for output. And don't forget you'll still have to special-case broadway: 1-10-11-12-13. – Lee Daniel Crocker May 25 '18 at 16:15

1 Answers1

-5

You can find all substrings of the current hand, and filter the results to find those that are sorted with an increment of 1:

def stringify_result(f):
  def wrapper(_d):
    cards = {10:'T', 11:'J', 12:'Q', 13:'K'}
    return list(map(lambda x:cards.get(x, str(x)), f(_d)))
  return wrapper

@stringify_result
def has_straight(d):
  cards = {'J': 11, 'K': 13, 'T': 10, 'Q': 12}
  subs = list(filter(None, [d[b:i] for i in range(len(d)+1) for b in range(len(d)+1)]))
  possibilities = list(filter(lambda x:all(x[i+1] - x[i] == 1 for i in range(len(x)-1)), [[int(cards.get(b, b)) for b in i] for i in subs]))
  return [] if not possibilities else max(possibilities, key=len)

straight = has_straight(['6', '8', '8', '9', 'T'])
score = len(straight)

Output:

['8', '9', 'T']
3

Edit: to account for multiple runs, you can use itertools.groupby:

import itertools
def has_straight(d):
   cards = {'J': 11, 'K': 13, 'T': 10, 'Q': 12}
   mutated_cards = list(map(lambda x:int(cards.get(x, x)), d))
   _grouped = [list(b) for _, b in itertools.groupby(mutated_cards)]
   subs = list(filter(None, [_grouped[b:i] for i in range(len(_grouped)+1) for b in range(len(_grouped)+1)]))
   final_filtered = list(filter(lambda x:all(x[i+1][0] - x[i][0] == 1 for i in range(len(x)-1)), subs))
   new_subs = [] if not final_filtered else max(final_filtered, key=lambda x:sum(len(i) for i in x))
   return sum(len(i) for i in new_subs if len(i) > 1), list(map(lambda x:x[0], new_subs))

print(has_straight(['6', '8', '8', '9', 'T']))
print(has_straight(['4', '4', '5', '5', '6']))

Output:

(2, [8, 9, 10])
(4, [4, 5, 6])
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • Hey thanks for the help. Do you know how I could alter this code to account for multiple runs? For example I should get 2 runs from the `['6', '8', '8', '9', 'T']` because there are two 8's meaning two 8,9,T sequences. Also for example: When I pass in `['4', '4', '5', '5', '6']` I only get back from has_straight `['4', '5']`. But I can see 4 runs that I should be getting back. Appreciate your time. – Coder117 May 24 '18 at 20:55