Files
project-euler/problem-54.py
2018-07-02 15:45:49 -04:00

160 lines
4.3 KiB
Python

import requests
url = 'https://projecteuler.net/project/resources/p054_poker.txt'
text = requests.get(url).text
hands = text.splitlines()
faces = {
'T': 10,
'J': 11,
'Q': 12,
'K': 13,
'A': 14
}
tests = [
'5H 5C 6S 7S KD 2C 3S 8S 8D TD',
'2C 3S 8S 8D TD 2C 5C 7D 8S QH',
'2D 9C AS AH AC 3D 6D 7D TD QD',
'4D 6S 9H QH QC 3D 6D 7H QD QS',
'2H 2D 4C 4D 4S 3C 3D 3S 9S 9D'
]
def is_straight(cards):
ranks = [x[0] for x in cards]
for idx, rank in enumerate(ranks):
try:
ranks[idx] = int(rank)
except ValueError:
ranks[idx] = faces[rank]
if max(ranks) - min(ranks) == 4 and len(set(ranks)) == 5:
return True
return False
def is_flush(cards):
suits = [x[1] for x in cards]
return all(x == suits[0] for x in suits)
def get_ranks(cards):
ranks = [x[0] for x in cards]
for idx, rank in enumerate(ranks):
try:
ranks[idx] = int(rank)
except ValueError:
ranks[idx] = faces[rank]
return ranks
def resolve_tie(hand_one, hand_two):
value = get_value(hand_one)
hand_one_ranks = get_ranks(hand_one)
hand_two_ranks = get_ranks(hand_two)
if is_straight(hand_one):
if max(hand_one_ranks) > max(hand_two_ranks):
return 0
else:
return 1
if value in [2, 3, 6, 7, 8]:
most_common_one = max(set(hand_one_ranks), key=hand_one_ranks.count)
most_common_two = max(set(hand_two_ranks), key=hand_two_ranks.count)
if most_common_one > most_common_two:
return 0
elif most_common_two > most_common_one:
return 1
else:
if value not in [6, 8]:
raise Exception('second level tie needed')
for idx, card in enumerate(sorted(hand_one_ranks)[::-1]):
if card > sorted(hand_two_ranks)[-1-idx]:
return 0
if card < sorted(hand_two_ranks)[-1-idx]:
return 1
def get_value(cards):
assert len(cards) == 5
ranks = [x[0] for x in cards]
for idx, rank in enumerate(ranks):
try:
ranks[idx] = int(rank)
except ValueError:
ranks[idx] = faces[rank]
flush = is_flush(cards)
straight = is_straight(cards)
groups = {}
for card in ranks:
try:
groups[card] += 1
except KeyError:
groups[card] = 1
print(groups)
group_most = max(groups.values())
if flush and sorted(ranks) == [10, 11, 12, 13, 14]:
# royal flush
return 0
elif flush and straight:
# straight flush
return 1
elif group_most == 4:
# four of a kind
return 2
elif len(groups) == 2 and group_most == 3:
# full house
return 3
elif flush:
# flush
return 4
elif straight:
# straight
return 5
elif group_most == 3:
# three of a kind
return 6
elif group_most == 2 and len(groups) == 3:
# two pair
return 7
elif group_most == 2 and len(groups) == 4:
# pair
return 8
else:
# high card
return 9
if __name__ == '__main__':
results = {'player_one': 0, 'player_two': 0}
for idx, hand in enumerate(hands):
print(idx)
hand = hand.split(' ')
player_one = hand[:5]
player_two = hand[5:]
player_one_value = get_value(player_one)
player_two_value = get_value(player_two)
print('player_one', player_one, player_one_value, is_flush(player_one), is_straight(player_one))
print('player_two', player_two, player_two_value, is_flush(player_two), is_straight(player_two))
if player_one_value == player_two_value:
if resolve_tie(player_one, player_two) == 0:
print('player_one_wins')
results['player_one'] += 1
elif resolve_tie(player_one, player_two) == 1:
print('player_two wins')
results['player_two'] += 1
elif player_one_value < player_two_value:
print('player_one wins')
results['player_one'] += 1
else:
print('player_two wins')
results['player_two'] += 1
print(results)