Reputation: 6597
The below poker hand evaluator is generating a ranking of the different cards the players are holding. It works well in Python 2 but it doesn't work in python 3 because the sort function can no longer compare tuples to integers. How can I make it behave in python 3 the way it used to behave in python 2?
The sorting needs to decide which cards are the best:
(1, (11, 8, 7, 6, 2)) # high card 11 (rank5)
(1, (12, 11, 8, 7, 2)) # high card 12 (rank4)
((3, 2), (11, 12)) # full house (triple and pair) (rank1)
((2, 1, 1, 1), (12, 11, 7, 6)) # pair of 12 (rank3)
((3, 1, 1), (12, 6, 3)) # three of 12 (rank2)
If an integer is compared to a tuple, then the first item of the tuple should be relevant. The sort function in python 2 would correctly sort the above, but in python 3 I get an error message the integers cannot be compared to tuples.
How do I need to adapt the keyfunction?
def keyfunction(x):
v= x[1]
return v
def poker(hands):
scores = [(i, score(hand.split())) for i, hand in enumerate(hands)]
#print (scores)
winner = sorted(scores , key=keyfunction)[-1][0]
return hands[winner]
def score(hand):
ranks = '23456789TJQKA'
rcounts = {ranks.find(r): ''.join(hand).count(r) for r, _ in hand}.items()
#print (rcounts)
score, ranks = zip(*sorted((cnt, rank) for rank, cnt in rcounts)[::-1])
if len(score) == 5:
if ranks[0:2] == (12, 3): #adjust if 5 high straight
ranks = (3, 2, 1, 0, -1)
straight = ranks[0] - ranks[4] == 4
flush = len({suit for _, suit in hand}) == 1
'''no pair, straight, flush, or straight flush'''
score = ([1, (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]
return score, ranks
poker(['8C TS KC 9H 4S','AC TS KC 9H 4S', 'AD AS KD KS KC', '9C AD KD AC 8C', 'AC 5H 8D AD AS'])
Upvotes: 0
Views: 145
Reputation: 1052
You could simply transform the integer indicating a high card when assigning score
into a one-element tuple.
...
score = ([(1, ), (3,1,1,1)], [(3,1,1,2), (5,)])[flush][straight]
...
Upvotes: 2