-
-
Save anonymous/816fe812ff2720e671fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Card(object): | |
def __init__(self, value, suit): | |
self.value = int(value) | |
self.suit = suit | |
def __str__(self): | |
return str(self.value) + self.suit | |
def __repr__(self): | |
return str(self.value) + self.suit | |
def __lt__(self, other): | |
return self.value < other.value | |
def read_file(name): | |
"""Return all non-empty lines of the file named `name`""" | |
with open(name) as f: | |
return filter(None, f.read().split('\n')) | |
def parse_cards(s): | |
"""Convert string of shorthand to list of Card objects for each hand""" | |
for r in [('T', '10'), ('J', '11'), ('Q', '12'), ('K', '13'), ('A', '14')]: | |
s = s.replace(*r) | |
l = [] | |
for c in s.split(): | |
l.append(Card(c[:-1], c[-1])) | |
return l[:5], l[5:] | |
def judge(a, b): | |
"""Return True if `a` is a better hand than `b`""" | |
def royal_flush(hand): | |
return straight_flush(hand) and hand[4].value == 14 | |
def straight_flush(hand): | |
return flush(hand) and straight(hand) | |
def four_of_a_kind(hand): | |
for i in xrange(2): | |
if len(set(c.value for c in hand[i:i+4])) == 1: | |
return hand[i].value | |
return False | |
def full_house(hand): | |
v = [c.value for c in hand] | |
return v[0] == v[1] and v[3] == v[4] and v[2] in (v[0], v[4]) | |
def flush(hand): | |
return len(set(c.suit for c in hand)) == 1 | |
def straight(hand): | |
# hand is a straight if every value is distinct and the highest one is 4 greater than the lowest | |
if len(set(c.value for c in hand)) == 5 and hand[0].value == hand[4].value - 4: | |
return True | |
# if highest card is an ace, treat it as 1 instead of 14 and try again | |
return hand[4].value == 14 and straight([Card(1, hand[4].suit)] + hand[:4]) | |
def three_of_a_kind(hand): | |
for i in xrange(3): | |
if len(set(c.value for c in hand[i:i+3])) == 1: | |
return hand[i].value | |
return False | |
def two_pairs(hand): | |
fake_hand = [c for c in hand if c.value != one_pair(hand)] | |
if hand == fake_hand: | |
return False | |
# put nonsense cards in fake_hand so we can check it for another pair | |
fake_hand.extend([Card(-1, 'Z'), Card(-2, 'Z')]) | |
return one_pair(fake_hand) and (one_pair(hand), one_pair(fake_hand)) | |
def one_pair(hand): | |
for i in xrange(4): | |
if len(set(c.value for c in hand[i:i+2])) == 1: | |
return hand[i].value | |
return False | |
def high_card(a, b): | |
"""Return True if `a` has the highest value card that `a` and `b` don't share | |
Used when resolving ties or if both hands are garbage""" | |
a, b = [c.value for c in a], [c.value for c in b] | |
c = sorted(set(a + b), reverse=True) | |
for v in c: | |
if (v in a) != (v in b): | |
return v in a | |
a, b = sorted(a), sorted(b) | |
if royal_flush(a): return True | |
if royal_flush(b): return False | |
if straight_flush(a): | |
if straight_flush(b): | |
return high_card(a, b) | |
return True | |
if straight_flush(b): | |
return False | |
if four_of_a_kind(a): | |
if four_of_a_kind(a) == four_of_a_kind(b): | |
return high_card(a, b) | |
return four_of_a_kind(a) > four_of_a_kind(b) | |
if four_of_a_kind(b): | |
return False | |
if full_house(a): | |
if full_house(b): | |
return high_card(a, b) | |
return True | |
if full_house(b): | |
return False | |
if flush(a): | |
if flush(b): | |
return high_card(a, b) | |
return True | |
if flush(b): | |
return False | |
if straight(a): | |
if straight(b): | |
return high_card(a, b) | |
return True | |
if straight(b): | |
return False | |
if three_of_a_kind(a): | |
if three_of_a_kind(a) == three_of_a_kind(b): | |
return high_card(a, b) | |
return three_of_a_kind(a) > three_of_a_kind(b) | |
if three_of_a_kind(b): | |
return False | |
if two_pairs(a): | |
if two_pairs(b): | |
if two_pairs(a)[0] == two_pairs(b)[0]: | |
if two_pairs(a)[1] == two_pairs(b)[1]: | |
return high_card(a, b) | |
return two_pairs(a)[1] > two_pairs(b)[1] | |
return two_pairs(a)[0] > two_pairs(b)[0] | |
return True | |
if two_pairs(b): | |
return False | |
if one_pair(a): | |
if one_pair(a) == one_pair(b): | |
return high_card(a, b) | |
return one_pair(a) > one_pair(b) | |
if one_pair(b): | |
return False | |
return high_card(a, b) | |
def main(): | |
rounds = map(parse_cards, read_file('poker.txt')) | |
# rounds[n][0] -> p1's hand in round n | |
# rounds[n][1] -> p2's hand in round n | |
print sum(judge(*r) for r in rounds) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment