values = { '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14 } colors = { 'H': 1, 'C': 2, 'S': 3, 'D': 4 } def handvalue(hand): return values[hand[0]]*10 + colors[hand[1]] def count_cards(hand): hand = [ x/10 for x in hand ] counter = { } for c in hand: if c in counter: counter[c] += 1 else: counter[c] = 1 return counter def high_card(hand): hand = [ x/10 for x in hand ] hand.sort() return hand[-1] def is_flush(hand): return (hand[0]%10 == hand[1]%10 == hand[2]%10 == hand[3]%10 == hand[4]%10) def is_straight(hand): hand = [ x/10 for x in hand ] hand.sort() return (hand[4] == hand[3]+1 == hand[2]+2 == hand[1]+3 == hand[0]+4) def is_straight_flush(hand): return is_flush(hand) and is_straight(hand) def is_royal_flush(hand): return is_straight_flush(hand) and high_card(hand) == values['A'] def is_n_of_a_kind(hand, n): counter = count_cards(hand) for c in counter: if counter[c] == n: return True return False def is_four_of_a_kind(hand): return is_n_of_a_kind(hand, 4) def is_three_of_a_kind(hand): return is_n_of_a_kind(hand, 3) def is_one_pair(hand): return is_n_of_a_kind(hand, 2) def is_two_pairs(hand): counter = count_cards(hand) pairs = 0 for c in counter: if counter[c] == 2 or counter[c] == 3: pairs += 1 return pairs == 2 def is_full_house(hand): return is_two_pairs(hand) and is_three_of_a_kind(hand) def better_hand(hand1, hand2): # both are straight flush if is_straight_flush(hand1): if high_card(hand1) > high_card(hand2): return 1 else: return 2 # both are four of a kind if is_four_of_a_kind(hand1): count1 = count_cards(hand1) count2 = count_cards(hand2) value4_1 = 0 value4_2 = 0 for c in count1: if count1[c] == 4: value4_1 = c break for c in count2: if count2[c] == 4: value4_2 = c break if value4_1 > value4_2: return 1 else: return 2 # both are full house if is_full_house(hand1): count1 = count_cards(hand1) count2 = count_cards(hand2) value3_1 = 0 value3_2 = 0 for c in count1: if count1[c] == 3: value3_1 = c break for c in count2: if count2[c] == 3: value3_2 = c break if value3_1 > value3_2: return 1 else: return 2 # both are flush if is_flush(hand1): hand1 = [ x/10 for x in hand1 ] hand2 = [ x/10 for x in hand2 ] hand1.sort() hand2.sort() for i in range(0, 5): if hand1[4-i] > hand2[4-i]: return 1 elif hand2[4-i] > hand1[4-i]: return 2 print "ERROR: no winner with hands: ", hand1, hand2 # should never be reached # both are straight if is_straight(hand1): if high_card(hand1) > high_card(hand2): return 1 else: return 2 # both are three of a kind if is_three_of_a_kind(hand1): count1 = count_cards(hand1) count2 = count_cards(hand2) value3_1 = 0 value3_2 = 0 for c in count1: if count1[c] == 3: value3_1 = c break for c in count2: if count2[c] == 3: value3_2 = c break if value3_1 > value3_2: return 1 else: return 2 # both are two pairs if is_two_pairs(hand1): count1 = count_cards(hand1) count2 = count_cards(hand2) value2_1 = [] value1_1 = 0 value2_2 = [] value1_2 = 0 for c in count1: if count1[c] == 2: value2_1.append(c) elif count1[c] == 1: value1_1 = c for c in count2: if count2[c] == 2: value2_2.append(c) elif count1[c] == 1: value1_2 = c value2_1.sort() value2_2.sort() if value2_1[1] > value2_2[1]: return 1 elif value2_2[1] > value2_1[1]: return 2 elif value2_1[0] > value2_2[0]: return 1 elif value2_2[0] > value2_1[0]: return 2 elif value1_1 > value1_2: return 1 else: return 2 # both are one pair if is_one_pair(hand1): count1 = count_cards(hand1) count2 = count_cards(hand2) value2_1 = 0 value1_1 = [] value2_2 = 0 value1_2 = [] for c in count1: if count1[c] == 2: value2_1 = c elif count1[c] == 1: value1_1.append(c) for c in count2: if count2[c] == 2: value2_2 = c elif count2[c] == 1: value1_2.append(c) value1_1.sort() value1_2.sort() if value2_1 > value2_2: return 1 elif value2_2 > value2_1: return 2 elif high_card(value1_1) > high_card(value1_2): return 1 else: return 2 # both are high card if high_card(hand1) > high_card(hand2): return 1 else: return 2 def rank(hand): if is_royal_flush(hand): return 10 if is_straight_flush(hand): return 9 if is_four_of_a_kind(hand): return 8 if is_full_house(hand): return 7 if is_flush(hand): return 6 if is_straight(hand): return 5 if is_three_of_a_kind(hand): return 4 if is_two_pairs(hand): return 3 if is_one_pair(hand): return 2 return 1 # high card def winner(hand1, hand2): if rank(hand1) > rank(hand2): return 1 if rank(hand2) > rank(hand1): return 2 return better_hand(hand1, hand2) hands = [] f = open('054.txt', 'r') for line in f: line.rstrip('\n') hands.append([ handvalue(x) for x in line.split(' ') ]) f.close() count_win1 = 0 for h in hands: hand1 = h[:5] hand2 = h[5:] if winner(hand1, hand2) == 1: count_win1 += 1 print count_win1