301 lines
10 KiB
Plaintext
301 lines
10 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Problem Name (Euler Problem 54)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"source": [
|
|
"In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way:\n",
|
|
"\n",
|
|
"* High Card: Highest value card.\n",
|
|
"* One Pair: Two cards of the same value.\n",
|
|
"* Two Pairs: Two different pairs.\n",
|
|
"* Three of a Kind: Three cards of the same value.\n",
|
|
"* Straight: All cards are consecutive values.\n",
|
|
"* Flush: All cards of the same suit.\n",
|
|
"* Full House: Three of a kind and a pair.\n",
|
|
"* Four of a Kind: Four cards of the same value.\n",
|
|
"* Straight Flush: All cards are consecutive values of same suit.\n",
|
|
"* Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.\n",
|
|
"* The cards are valued in the order:\n",
|
|
"* 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.\n",
|
|
"\n",
|
|
"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.\n",
|
|
"\n",
|
|
"Consider the following five hands dealt to two players:\n",
|
|
"\n",
|
|
"| Hand | \tPlayer 1\t|\tPlayer 2\t| \tWinner |\n",
|
|
"|------|------------|-----------|----------|\n",
|
|
"| 1\t | \t5H 5C 6S 7S KD Pair of Fives | 2C 3S 8S 8D TD Pair of Eights | Player 2 |\n",
|
|
"| 2\t | \t5D 8C 9S JS AC Highest card Ace | 2C 5C 7D 8S QH Highest card Queen | Player 1 |\n",
|
|
"| 3\t | \t2D 9C AS AH AC Three Aces | 3D 6D 7D TD QD Flush with Diamonds | Player 2 |\n",
|
|
"| 4\t | \t4D 6S 9H QH QC Pair of Queens Highest card Nine | 3D 6D 7H QD QS Pair of Queens Highest card Seven | Player 1 |\n",
|
|
"| 5\t | \t2H 2D 4C 4D 4S Full House With Three Fours | 3C 3D 3S 9S 9D Full House with Three Threes | Player 1 |\n",
|
|
"\n",
|
|
"The file, poker.txt, contains one-thousand random hands dealt to two players.\n",
|
|
"Each line of the file contains ten cards (separated by a single space): the\n",
|
|
"first five are Player 1's cards and the last five are Player 2's cards. You can\n",
|
|
"assume that all hands are valid (no invalid characters or repeated cards), each\n",
|
|
"player's hand is in no specific order, and in each hand there is a clear\n",
|
|
"winner.\n",
|
|
"\n",
|
|
"How many hands does Player 1 win?\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Let's start with some helper functions."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def suit_to_value(suit):\n",
|
|
" return {\n",
|
|
" \"2\": 2,\n",
|
|
" \"3\": 3,\n",
|
|
" \"4\": 4,\n",
|
|
" \"5\": 5,\n",
|
|
" \"6\": 6,\n",
|
|
" \"7\": 7,\n",
|
|
" \"8\": 8,\n",
|
|
" \"9\": 9,\n",
|
|
" \"T\": 10,\n",
|
|
" \"J\": 11,\n",
|
|
" \"Q\": 12,\n",
|
|
" \"K\": 13,\n",
|
|
" \"A\": 14,\n",
|
|
" }[suit]\n",
|
|
"\n",
|
|
"assert(suit_to_value('K') == 13)\n",
|
|
"\n",
|
|
"\n",
|
|
"def is_flush(colors):\n",
|
|
" first_color = colors[0]\n",
|
|
" for color in colors:\n",
|
|
" if color != first_color:\n",
|
|
" return False\n",
|
|
" return True\n",
|
|
"\n",
|
|
"\n",
|
|
"assert(is_flush([\"H\", \"H\", \"H\", \"H\", \"H\"]))\n",
|
|
"assert(is_flush([\"H\", \"H\", \"D\", \"H\", \"H\"]) == False)\n",
|
|
"\n",
|
|
"def is_straight(suits):\n",
|
|
" suits = sorted(suits)\n",
|
|
" first_suit = suits[0]\n",
|
|
" for suit in suits[1:]:\n",
|
|
" if first_suit + 1 != suit:\n",
|
|
" return False\n",
|
|
" first_suit = suit\n",
|
|
" return True\n",
|
|
"\n",
|
|
"assert(is_straight([6,3,4,5,7]))\n",
|
|
"assert(is_straight([6,3,4,5,8]) == False)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 37,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def get_numbered_groups(ns):\n",
|
|
" \"\"\" Takes [0, 3, 0, 3, 1] and returns\n",
|
|
" [(2, 3), (2, 0), (1, 1)]\n",
|
|
" \"\"\"\n",
|
|
" rs = []\n",
|
|
" current_group = []\n",
|
|
" for n in sorted(ns, reverse=True):\n",
|
|
" if not current_group or n in current_group:\n",
|
|
" current_group.append(n)\n",
|
|
" else:\n",
|
|
" rs.append(current_group)\n",
|
|
" current_group = [n]\n",
|
|
" rs.append(current_group)\n",
|
|
" rs = sorted([(len(r), r[0]) for r in rs], reverse=True)\n",
|
|
" return rs\n",
|
|
"\n",
|
|
"assert(get_numbered_groups([0, 3, 0, 3, 1]) == [(2, 3), (2, 0), (1, 1)])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Let's put that stuff together."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 45,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def rank(hand):\n",
|
|
" \"\"\" A hand must be provided as a list of two letter strings.\n",
|
|
" The first letter is the suit and the second the suit of a card.\n",
|
|
" \n",
|
|
" The function returns a tuple. The first value represents the hand as an integer\n",
|
|
" where 0 means high card and 9 means Straight Flush. The second value is a list of integers\n",
|
|
" ranking the value of the respective rank. For example, a Royal Flush would be (9, [14, 13, 12, 11, 10]),\n",
|
|
" while 22aqj would be (1, [2, 2, 14, 12, 11]). By doing this we can simply compare to hands\n",
|
|
" by first comparing the rank itself and then the list of integers.\n",
|
|
" \n",
|
|
" We get something like [\"5H\", \"6S\", \"7S\", \"5C\", \"KD\"].\n",
|
|
" \"\"\"\n",
|
|
" \n",
|
|
" suits, colors = zip(*(map(lambda s: (s[0], s[1]), hand)))\n",
|
|
" suits = sorted(map(suit_to_value, suits))\n",
|
|
"\n",
|
|
" flush = is_flush(colors)\n",
|
|
" straight = is_straight(suits)\n",
|
|
" numbered_suits = get_numbered_groups(suits)\n",
|
|
" if flush and straight:\n",
|
|
" return [8, numbered_suits]\n",
|
|
" if flush:\n",
|
|
" return [5, numbered_suits]\n",
|
|
" if straight:\n",
|
|
" return [4, numbered_suits]\n",
|
|
" if numbered_suits[0][0] == 4:\n",
|
|
" return [7, numbered_suits]\n",
|
|
" if numbered_suits[0][0] == 3 and numbered_suits[1][0] == 2:\n",
|
|
" return [6, numbered_suits]\n",
|
|
" if numbered_suits[0][0] == 3:\n",
|
|
" return [3, numbered_suits]\n",
|
|
" if numbered_suits[0][0] == 2 and numbered_suits[1][0] == 2:\n",
|
|
" return [2, numbered_suits]\n",
|
|
" if numbered_suits[0][0] == 2:\n",
|
|
" return [1, numbered_suits]\n",
|
|
" return [0, numbered_suits]\n",
|
|
" \n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 55,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"assert(rank([\"5H\", \"5C\", \"6S\", \"7S\", \"KD\"]) == [1, [(2, 5), (1, 13), (1, 7), (1, 6)]]) # Pair of Fives\n",
|
|
"assert(rank([\"5D\", \"8C\", \"9S\", \"JS\", \"AC\"]) == [0, [(1, 14), (1, 11), (1, 9), (1, 8), (1, 5)]]) # Highest card Ace\n",
|
|
"assert(rank([\"2D\", \"9C\", \"AS\", \"AH\", \"AC\"]) == [3, [(3, 14), (1, 9), (1, 2)]]) # Three Aces\n",
|
|
"assert(rank([\"4D\", \"6S\", \"9H\", \"QH\", \"QC\"]) == [1, [(2, 12), (1, 9), (1, 6), (1, 4)]]) # Pair of Queens Highest card Nine\n",
|
|
"assert(rank([\"2H\", \"2D\", \"4C\", \"4D\", \"4S\"]) == [6, [(3, 4), (2, 2)]]) # Full House With Three Fours\n",
|
|
"assert(rank([\"2C\", \"3S\", \"8S\", \"8D\", \"TD\"]) == [1, [(2, 8), (1, 10), (1, 3), (1, 2)]]) # Pair of Eights \n",
|
|
"assert(rank([\"2C\", \"5C\", \"7D\", \"8S\", \"QH\"]) == [0, [(1, 12), (1, 8), (1, 7), (1, 5), (1, 2)]]) # Highest card Queen \n",
|
|
"assert(rank([\"3D\", \"6D\", \"7D\", \"TD\", \"QD\"]) == [5, [(1, 12), (1, 10), (1, 7), (1, 6), (1, 3)]]) # Flush with Diamonds \n",
|
|
"assert(rank([\"3D\", \"6D\", \"7H\", \"QD\", \"QS\"]) == [1, [(2, 12), (1, 7), (1, 6), (1, 3)]]) # Pair of Queens Highest card Seven \n",
|
|
"assert(rank([\"3C\", \"3D\", \"3S\", \"9S\", \"9D\"]) == [6, [(3, 3), (2, 9)]]) # Full House with Three Threes \n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 67,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def read_hands():\n",
|
|
" \"\"\" Reads a list of tuples where each field\n",
|
|
" in the tuple represents a hand.\n",
|
|
" \"\"\"\n",
|
|
" hands = []\n",
|
|
" with open(\"EulerProblem054.txt\", \"r\") as f:\n",
|
|
" for line in f.readlines():\n",
|
|
" cards = line.strip().split(\" \")\n",
|
|
" hands.append((cards[:5], cards[5:]))\n",
|
|
" return hands\n",
|
|
"\n",
|
|
"p1_wins = 0\n",
|
|
"\n",
|
|
"for p1_hand, p2_hand in read_hands():\n",
|
|
" if rank(p1_hand) > rank(p2_hand):\n",
|
|
" p1_wins += 1\n",
|
|
" msg = \"P1 hand {} wins over P2 hand {}.\"\n",
|
|
" #print(msg.format(p1_hand, p2_hand))\n",
|
|
" else:\n",
|
|
" msg = \"P1 hand {} loses versus P2 hand {}.\"\n",
|
|
" #print(msg.format(p1_hand, p2_hand))\n",
|
|
" \n",
|
|
"s = p1_wins "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 70,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"376\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(s)\n",
|
|
"assert(s == 376)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"completion_date": "Mon, 24 Dec 2018, 23:30",
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python3.6",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.6.5"
|
|
},
|
|
"tags": [
|
|
"poker",
|
|
"airplane"
|
|
]
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|