Skip to content

Instantly share code, notes, and snippets.

@Per48edjes
Last active June 4, 2024 18:05
Show Gist options
  • Save Per48edjes/5ab7c9262482ea6fc94fa757190c7135 to your computer and use it in GitHub Desktop.
Save Per48edjes/5ab7c9262482ea6fc94fa757190c7135 to your computer and use it in GitHub Desktop.
Fiddler on the Proof: Fiddler (05/24/2024)
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "6479454d-d434-4808-a73d-01255eed4844",
"metadata": {},
"source": [
"# Fiddler on the Proof\n",
"\n",
"Ravi Dayabhai & Conrad Warren 🃏 2024-05-24"
]
},
{
"cell_type": "markdown",
"id": "52b23e3c-c3d9-4a10-87b0-8f3910e19419",
"metadata": {},
"source": [
"## Problem\n",
"\n",
"You’re playing a modified version of blackjack, where the deck consists of exactly 10 cards numbered 1 through 10. Unlike traditional blackjack, in which the ace can count as 1 or 11, the 1 here always has a value of 1.\n",
"\n",
"You shuffle the deck so the order of the cards is completely random, after which you draw one card at a time. You keep drawing until the sum of your drawn cards is at least 21. If the sum is exactly 21, you win! But if the sum is greater than 21, you “bust,” or lose. \n",
"\n",
"What are your chances of winning, that is, of drawing a sum that is exactly 21?"
]
},
{
"cell_type": "markdown",
"id": "eaa13279-6073-4c6d-8fa7-e57145e55b49",
"metadata": {},
"source": [
"## Solution\n",
"\n",
"The probability of winning (read: having a hand whose sum is 21) is $\\frac{635040}{10!} = 0.175$."
]
},
{
"cell_type": "markdown",
"id": "75277d57-d547-41e9-9813-88d90e03dc12",
"metadata": {},
"source": [
"### Rationale"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "1b332a50-ea57-4eca-8970-f72aa466ab19",
"metadata": {},
"outputs": [],
"source": [
"import itertools as it\n",
"import math\n",
"\n",
"DECK = list(range(1, 10 + 1))"
]
},
{
"cell_type": "markdown",
"id": "f3c98c23-7b94-4b91-8518-95165e5f1ac7",
"metadata": {},
"source": [
"The most straightforward approach that comes to mind is just to search the entire sample space for outcomes that result in winning (having a hand of value 21)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "06e69a52-6e0d-4eff-9541-5e245a7df274",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"p(win) = 0.175 = 635040 / 3628800\n"
]
}
],
"source": [
"N, event_blackjack = math.factorial(10), 0\n",
"for shuffle in it.permutations(DECK):\n",
" hand = 0\n",
" for card in shuffle:\n",
" hand += card\n",
" if hand < 21:\n",
" continue\n",
" event_blackjack += 1 if hand == 21 else 0\n",
" break\n",
"\n",
"p_blackjack = event_blackjack / N\n",
"\n",
"print(f\"p(win) = {p_blackjack} = {event_blackjack} / {N}\")"
]
},
{
"cell_type": "markdown",
"id": "e36aaa5a-7b65-46f8-8380-99ed738ae2cf",
"metadata": {},
"source": [
"## Problem (Extra Credit)\n",
"\n",
"Playing for 21 or bust is a risky strategy. From this moment on, you decide to be risk averse.\n",
"\n",
"You’re playing the same modified version of blackjack again, but this time, whenever there’s even the slightest chance you could bust on the next card, you quit the round and start over. On average, how many rounds should you expect to start until you finally win?"
]
},
{
"cell_type": "markdown",
"id": "b63e1cf2-949a-4314-b11a-510e29903d98",
"metadata": {},
"source": [
"## Solution\n",
"\n",
"On average, if you are \"risk averse\", you would have to play $\\frac{10!}{74880} \\approx 48.4615$ rounds until you win."
]
},
{
"cell_type": "markdown",
"id": "68a0ebf7-d311-4e41-9d66-023ac8cd1ed7",
"metadata": {},
"source": [
"### Rationale"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "571879b1-d296-4c9d-9717-657d781a9299",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"p(win) = 0.020634920634920634 = 74880 / 3628800\n"
]
}
],
"source": [
"event_blackjack_averse = 0\n",
"for shuffle in it.permutations(DECK):\n",
" hand, remaining = 0, set(shuffle)\n",
" for card in shuffle:\n",
" if max(remaining) + hand > 21:\n",
" break\n",
" hand += card\n",
" remaining.remove(card)\n",
" if hand == 21:\n",
" event_blackjack_averse += 1\n",
" break\n",
"\n",
"p_blackjack_averse = event_blackjack_averse / N\n",
"\n",
"print(f\"p(win) = {p_blackjack_averse} = {event_blackjack_averse} / {N}\")"
]
},
{
"cell_type": "markdown",
"id": "84ef7a33-2641-4483-b408-838ebcf59ac0",
"metadata": {},
"source": [
"Because rounds can be assumed to be independent and identically distributed, the number of rounds required to win can be modeled by a random variable $X \\sim \\text{Geom}(p)$, where $p$ is the probability of winning.\n",
"\n",
"Thus, $E(X) = \\frac{1}{p}$:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9dec8b6c-a34a-4427-befd-695eee23b755",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Average number of rounds to play (under risk aversion): 48.46153846153846\n"
]
}
],
"source": [
"print(f\"Average number of rounds to play (under risk aversion): {1 / p_blackjack_averse}\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8c1c70ce-73ae-4778-88a2-fbe9d785eb3e",
"metadata": {},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "markdown",
"id": "5dfb9646-8e5a-4ffb-b1f0-dc198f53dc6a",
"metadata": {},
"source": [
"#### Numerical Approximation\n",
"\n",
"Below, we run a simple simulation to verify the answer we calculated above."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f41d9f26-9c6e-407c-8e5b-e8b1aefff1ed",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Average number of rounds played (under risk aversion): 48.384721\n"
]
}
],
"source": [
"T = 1_000_000\n",
"deck = DECK.copy()\n",
"\n",
"rounds_played_total = 0\n",
"for _ in range(T):\n",
" rounds, won = 0, False\n",
" while not won:\n",
" rounds += 1\n",
" random.shuffle(deck) \n",
" hand, remaining = 0, set(deck)\n",
" for card in deck:\n",
" if max(remaining) + hand > 21:\n",
" break\n",
" hand += card\n",
" remaining.remove(card)\n",
" if hand == 21:\n",
" won = True\n",
" break\n",
" else:\n",
" rounds_played_total += rounds\n",
"\n",
"print(f\"Average number of rounds played (under risk aversion): {rounds_played_total / T}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"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.12.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment