Skip to content

Instantly share code, notes, and snippets.

/54.py Secret

Created December 30, 2014 16:39
Show Gist options
  • Save anonymous/816fe812ff2720e671fb to your computer and use it in GitHub Desktop.
Save anonymous/816fe812ff2720e671fb to your computer and use it in GitHub Desktop.
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