Last active
April 4, 2024 21:25
-
-
Save yangchenyun/6d586b6e1336203d29421563c9612172 to your computer and use it in GitHub Desktop.
Poker_Interview
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
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"<div style=\"text-align: right\"><i>Peter Norvig<br>2012<br>Updated 2020</i></div>\n", | |
"\n", | |
"# Poker: Ranking Hands, etc.\n", | |
"\n", | |
"\n", | |
"The [rules for poker hands](https://en.wikipedia.org/wiki/List_of_poker_hands) are complex, but it is an interesting exercise to write a program to rank poker hands.\n", | |
"\n", | |
"Some key concepts:\n", | |
"\n", | |
"- **Card**: A card will be represented as a two character string, like `'9c'`, where the first character is the **rank** and the second is the **suit**. The ranks are `23456789TJQKA` in ascending order of value and the suits are `'cdhs'` for clubs, diamonds, hearts, and spades; all suits have equal value in poker. \n", | |
"- **Hand**: A hand is a collection of five cards: `['3s', '3c', 'As', 'Ks', 'Qs']`\n", | |
"- **Type**: A hand has a ranking type; these are (in highest to lowest order): five of a kind, straight flush, four of a kind, full house, flush, straight, three of a kind, two pair, one pair, high card. (Five of a kind can only be made in games with wild cards.)\n", | |
"- **Group**: Two or more cards with the same rank: a pair, a three-of-a-kind, etc.\n", | |
"- **Winning**: If two hands have different types, the higher type wins. If they have the same type, a **tiebreaker** is needed. \n", | |
"- **Tiebreaker**: For example, the tiebreaker for \"straight\" is the rank of the highest card; a ten-high straight beats a nine-high straight. The tiebreaker for \"three of a kind\" is the rank of the three-of-a-kind group.\n", | |
"- **Ranking**: To determine which hand wins we could have a comparison function, it is simpler to compare ranks with `ranking(hand) < ranking(hand2)`. The function `ranking` returns a tuple that encompasses the type and tiebreaker. Note that the word **ranking** refers to the value of a *hand*, but **rank** refers to the value of a *card*." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def ranking(hand) -> tuple:\n", | |
" \"\"\"Return a (type, tiebreaker) tuple indicating how high the hand ranks.\"\"\"\n", | |
" pass" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Define main concepts\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Testing Poker Hands\n", | |
"\n", | |
"Below is a list of `hands`, with four examples of each **type**, all in descending ranking order (i.e. best to worst). The `test` function asserts that:\n", | |
"- The `ranking` function agrees with this ordering.\n", | |
"- The order of cards within a hand does not matter—every permutation of cards is ranked the same. \n", | |
"- Swapping the suits around (e.g. swapping every spade with every heart) does not change the ranking." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from itertools import permutations\n", | |
"cards = str.split # Function to split a string apart into a list of cards\n", | |
"\n", | |
"def the_same(things) -> bool: \n", | |
" \"\"\"Are all the things actually the same?\"\"\"\n", | |
" return len(set(things)) <= 1\n", | |
"\n", | |
"\n", | |
"hands = [cards(h) for h in ( \n", | |
" 'As Ks Qs Ts Js', 'Kc Qc Jc Tc 9c', '6d 5d 4d 3d 2d', '5h 4h 3h 2h Ah', # straight flush \n", | |
" 'As Ac Ad Ah 2s', '7s 7c 7d 2d 7h', '6s 6c 6d 6h 9s', 'As 5h 5c 5d 5s', # four of a kind \n", | |
" 'Th Tc Td 5h 5c', '9h 9c 9d 8c 8h', '6h 6c 6d Tc Th', '5c 5d 5s As Ah', # full house\n", | |
" 'As 2s 3s 4s 6s', 'Kc Qc Jc Tc 2c', 'Qc Jc Tc 9c 7c', '4h 5h 6h 7h 9h', # flush\n", | |
" 'As Kd Qc Td Jh', 'Kc Qh Jd Th 9c', '6c 5d 4h 3s 2s', 'As 2d 3c 4h 5s', # straight\n", | |
" 'As Ac Ad 2h 3h', 'Ts Tc Th 9s 8c', 'Ts Tc Th 9s 7c', '9h 9s 9d Ah Kh', # three of a kind\n", | |
" 'Ts Tc 5s 5c 8h', 'Ts Tc 5s 5c 7h', '9s 9c 8s 8c As', '3s 3c 2s 2d Ah', # two pair \n", | |
" 'As Ac 4c 5s 6s', '4s 4c As Ks Qs', '4h 4d Kh Qd Jd', '2d 2c Ad Kd Qd', # pair \n", | |
" 'Ah 3s 4s 5s 6s', 'Kh Qh Jh Th 8d', '7d 2s 4s 5s 6s', '7h 6s 5d 3s 2d', # high card\n", | |
" )]\n", | |
"\n", | |
"def test(ranking, hands=hands) -> bool:\n", | |
" \"\"\"Test that `ranking` preserves order of `hands`, and that permuting cards is irrelevant.\"\"\"\n", | |
" assert hands == sorted(hands, key=ranking, reverse=True)\n", | |
" trans = str.maketrans('shdc', 'hscd')\n", | |
" for hand in hands: \n", | |
" assert the_same(ranking(h) for h in permutations(hand))\n", | |
" assert the_same([ranking(hand), ranking([c.translate(trans) for c in hand])])\n", | |
" return len(hands)" | |
] | |
} | |
], | |
"metadata": { | |
"language_info": { | |
"name": "python" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment