Solution to problem 54
This commit is contained in:
parent
2df31ca1fb
commit
9555105815
134
src/Python/Problem054.py
Normal file
134
src/Python/Problem054.py
Normal file
@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Created on 27 Sep 2021
|
||||
|
||||
@author: David Doblas Jiménez
|
||||
@email: daviddoji@pm.me
|
||||
|
||||
Solution for problem 54 of Project Euler
|
||||
https://projecteuler.net/problem=54
|
||||
"""
|
||||
|
||||
from utils import timeit
|
||||
|
||||
|
||||
@timeit("Problem 54")
|
||||
def compute():
|
||||
"""
|
||||
In the card game poker, a hand consists of five cards and are ranked,
|
||||
from lowest to highest, in the following way:
|
||||
|
||||
High Card: Highest value card.
|
||||
One Pair: Two cards of the same value.
|
||||
Two Pairs: Two different pairs.
|
||||
Three of a Kind: Three cards of the same value.
|
||||
Straight: All cards are consecutive values.
|
||||
Flush: All cards of the same suit.
|
||||
Full House: Three of a kind and a pair.
|
||||
Four of a Kind: Four cards of the same value.
|
||||
Straight Flush: All cards are consecutive values of same suit.
|
||||
Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
|
||||
|
||||
The cards are valued in the order:
|
||||
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
|
||||
|
||||
If two players have the same ranked hands then the rank made up of the
|
||||
highest value wins; for example, a pair of eights beats a pair of fives
|
||||
(see example 1 below). But if two ranks tie, for example, both players
|
||||
have a pair of queens, then highest cards in each hand are compared
|
||||
(see example 4 below); if the highest cards tie then the next highest
|
||||
cards are compared, and so on.
|
||||
|
||||
Consider the following five hands dealt to two players:
|
||||
|
||||
Hand Player 1 Player 2 Winner
|
||||
1 5H 5C 6S 7S KD 2C 3S 8S 8D TD Player 2
|
||||
Pair of Fives Pair of Eights
|
||||
2 5D 8C 9S JS AC 2C 5C 7D 8S QH Player 1
|
||||
Highest card Ace Highest card Queen
|
||||
3 2D 9C AS AH AC 3D 6D 7D TD QD Player 2
|
||||
Three Aces Flush with Diamonds
|
||||
4 4D 6S 9H QH QC 3D 6D 7H QD QS Player 1
|
||||
Pair of Queens Pair of Queens
|
||||
Highest card Nine Highest card Seven
|
||||
5 2H 2D 4C 4D 4S 3C 3D 3S 9S 9D Player 1
|
||||
Full House Full House
|
||||
With Three Fours with Three Threes
|
||||
|
||||
The file, poker.txt, contains one-thousand random hands dealt to two
|
||||
players. Each line of the file contains ten cards (separated by a single
|
||||
space): the first five are Player 1's cards and the last five are Player
|
||||
2's cards. You can assume that all hands are valid (no invalid characters
|
||||
or repeated cards), each player's hand is in no specific order, and in
|
||||
each hand there is a clear winner.
|
||||
|
||||
How many hands does Player 1 win?
|
||||
"""
|
||||
|
||||
# 3 help functions.
|
||||
def replace_values_in_string(text: str, args_dict: dict) -> str:
|
||||
for k, v in args_dict.items():
|
||||
text = text.replace(k, str(v))
|
||||
return text
|
||||
|
||||
def n_of_a_kind(hand: list, n: int) -> int:
|
||||
return max([x for x in hand if hand.count(x) == n] or [0])
|
||||
|
||||
def to_numerical(hand: list) -> list:
|
||||
return sorted([int(x[:-1]) for x in hand], reverse=True)
|
||||
|
||||
|
||||
# 10 Ranks functions.
|
||||
def high_card(str_hand: list) -> list:
|
||||
return to_numerical(str_hand)
|
||||
|
||||
def one_pair(hand: list) -> int:
|
||||
return n_of_a_kind(hand, 2)
|
||||
|
||||
def two_pair(hand: list) -> int:
|
||||
pairs = set([x for x in hand if hand.count(x) == 2])
|
||||
return 0 if len(pairs) < 2 else max(pairs)
|
||||
|
||||
def three_of_a_kind(hand: list) -> int:
|
||||
return n_of_a_kind(hand, 3)
|
||||
|
||||
def straight(hand: list) -> int:
|
||||
return 0 if not list(range(hand[0], hand[-1]-1, -1)) == hand else max(hand)
|
||||
|
||||
def flush(str_hand: list) -> bool:
|
||||
return len(set([x[-1] for x in str_hand])) == 1
|
||||
|
||||
def full_house(hand: list) -> int:
|
||||
return three_of_a_kind(hand) if one_pair(hand) and three_of_a_kind(hand) else 0
|
||||
|
||||
def four_of_a_kind(hand: list) -> int:
|
||||
return n_of_a_kind(hand, 4)
|
||||
|
||||
def straight_flush(str_hand: list) -> int:
|
||||
straight_result = straight(to_numerical(str_hand))
|
||||
return straight_result if straight_result and flush(str_hand) else 0
|
||||
|
||||
def royal_flush(str_hand: list) -> bool:
|
||||
return flush(str_hand) and list(range(14, 9, -1)) == to_numerical(str_hand)
|
||||
|
||||
|
||||
replace_map = {"T": 10, "J": 11, "Q": 12, "K": 13, "A": 14}
|
||||
score = [0, 0]
|
||||
for line in open("../files/Problem54.txt", "r").read().splitlines():
|
||||
line = replace_values_in_string(line, replace_map).split()
|
||||
hands = line[:5], line[5:]
|
||||
for rank in (royal_flush, straight_flush, four_of_a_kind, full_house, flush,
|
||||
straight, three_of_a_kind, two_pair, one_pair, high_card):
|
||||
should_convert_hand = "str" not in rank.__code__.co_varnames[0] # Checks parameter name.
|
||||
result = [rank(to_numerical(hand) if should_convert_hand else hand) for hand in hands]
|
||||
if result[0] != result[1]:
|
||||
score[0 if result[0] > result[1] else 1] += 1
|
||||
break
|
||||
|
||||
return score[0]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
print(f"Result for Problem 54: {compute()}")
|
Loading…
x
Reference in New Issue
Block a user