-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathp054.py
More file actions
51 lines (40 loc) · 1.68 KB
/
p054.py
File metadata and controls
51 lines (40 loc) · 1.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# This solution would not have been possible without https://blog.dreamshire.com/project-euler-54-solution/
# It took a while for me to fully understand what was happening, but I have worked through it and made
# comments to try and clarify what is happening in this concise and powerful code piece
from collections import Counter
hands = (line.split() for line in open('p054.txt'))
# Convert cards to numbers
# T, J, Q, K, A = 10, 11, 12, 13, 14
VALUES = {r: i for i, r in enumerate('23456789TJQKA', 2)}
STRAIGHTS = [(v, v-1, v-2, v-3, v-4)
for v in range(14, 5, -1)] + [(14, 5, 4, 3, 2)]
# high card, one pair, two pair, three of a kind, straight, flush, full house, four of a kind
RANKS = [(1, 1, 1, 1, 1), (2, 1, 1, 1), (2, 2, 1),
(3, 1, 1), (), (), (3, 2), (4, 1)]
def hand_rank(hand):
"""
Count number of each card
Ex: ['8C', 'TS', 'KC', '9H', '4S'] =>
[(1, 13), (1, 10), (1, 9), (1, 8), (1, 4)] =>
[(1, 1, 1, 1, 1), (13, 10, 9, 8, 4)]
"""
score_zip = zip(*sorted(((v, VALUES[k]) for
k, v in Counter(x[0] for x in hand).items()), reverse=True))
score = list(score_zip)
score[0] = RANKS.index(score[0])
if len(set(card[1] for card in hand)) == 1:
score[0] = 5 # flush
if score[1] in STRAIGHTS:
if score[0] == 5:
score[0] = 8
else:
score[0] = 4
return score
def compute():
"""
Since tuples can be compared, royal flushes will have a score > straight flush
Ex: [8, (9, 8, 7, 6, 5)] < [8, (14, 13, 12, 11, 10)]
"""
return sum(hand_rank(hand[:5]) > hand_rank(hand[5:]) for hand in hands)
if __name__ == "__main__":
print(compute())