Created
May 8, 2021 01:24
-
-
Save kmcelwee/f7aaccf92b366352dbe33a26ad1bda65 to your computer and use it in GitHub Desktop.
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": [ | |
"# Determining optimal banking strategy in the game show \"The Weakest Link\"\n", | |
"The Weakest Link has a group of people answer questions in a circle. For each correct answer, the team can go up the totem pole of values they can \"bank.\" Once a member banks or gets a question wrong, the amount that can be banked returns to 0. Here is the money ladder: [0, 250, 500, 1000, 1500, 2250, 3000, 4000, 5000]\n", | |
"\n", | |
"For example, if Player 1 gets a question correct, Player2 can bank 100 pounds. If Player2 gets the next question correct, Player3 can bank 250 pounds, and so on. But if Player2 gets the question wrong, Player3 cannot bank anything and the team must start climbing the money ladder all over again. What is the optimal stopping strategy? Should players hedge their bets after reaching 500 pounds? 4000? What if they are really talented? Or not very skillful?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"import matplotlib.pyplot as plt\n", | |
"import random\n", | |
"import plotly.plotly as py\n", | |
"import plotly.tools as tls\n", | |
"import plotly.graph_objs as go\n", | |
"\n", | |
"%matplotlib inline" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Create game function" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# These are the payment levels\n", | |
"pounds = [0, 250, 500, 1000, 1500, 2250, 3000, 4000, 5000]\n", | |
"\n", | |
"def runGame(skill, threshold, N):\n", | |
" '''\n", | |
" Run a hypothetical round of The Weakest Link. Skill is the likelihood of getting an answer correct,\n", | |
" threshold is the number of turns a player waits before banking, and N is the number of questions asked.\n", | |
" '''\n", | |
" now = 0\n", | |
" bank = 0\n", | |
" for i in range(N):\n", | |
" questionRight = random.randint(1, 101) <= skill\n", | |
" if questionRight:\n", | |
" now += 1\n", | |
" else:\n", | |
" now = 0\n", | |
" \n", | |
" if now == threshold:\n", | |
" bank += pounds[now]\n", | |
" now = 0\n", | |
" \n", | |
" if now < threshold:\n", | |
" bank += pounds[now]\n", | |
" \n", | |
" return bank" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Testing" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# N is the number of questions, B is the number of tests to average over\n", | |
"N, B = 100, 500 \n", | |
"\n", | |
"skill = range(101)\n", | |
"threshold = range(0, 9)\n", | |
"results = np.zeros([len(skill), len(threshold)])\n", | |
"for i, s in enumerate(skill):\n", | |
" for j, t in enumerate(threshold):\n", | |
" allTests = np.array([runGame(s, t, N=N) for _ in range(B)])\n", | |
" results[i, j] = allTests.mean()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Analysis" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https://plot.ly/~kevinrmcelwee/57.embed\" height=\"576px\" width=\"576px\"></iframe>" | |
], | |
"text/plain": [ | |
"<plotly.tools.PlotlyDisplay object>" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(8, 8))\n", | |
"ax.set_title('Heatmap of winnings when comparing skill to turns waited')\n", | |
"ax.set_xlabel('Number of turns before banking')\n", | |
"ax.set_ylabel('Percent skill')\n", | |
"plotly_fig = tls.mpl_to_plotly(fig)\n", | |
"\n", | |
"trace = dict(z=results, type='heatmap', zmin=0)\n", | |
"plotly_fig.add_traces([trace])\n", | |
"\n", | |
"plotly_fig['layout']['xaxis'].update({'autorange':True})\n", | |
"plotly_fig['layout']['yaxis'].update({'autorange':True})\n", | |
"\n", | |
"py.iplot(plotly_fig, filename='weakestLinkHeatMap')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https://plot.ly/~kevinrmcelwee/59.embed\" height=\"360px\" width=\"864px\"></iframe>" | |
], | |
"text/plain": [ | |
"<plotly.tools.PlotlyDisplay object>" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"rec_stop = [np.argmax(results[i, :]) for i in range(len(skill))]\n", | |
"rec_value = [results[i, :].max() for i in range(len(skill))]\n", | |
"\n", | |
"fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))\n", | |
"axes[0].barh(width=rec_stop, y=[i for i in range(len(skill))])\n", | |
"axes[0].set_ylabel('percent skill')\n", | |
"axes[0].set_xlabel('recommended number of turns players should wait')\n", | |
"axes[1].set_ylabel('percent skill')\n", | |
"axes[1].set_xlabel('total winnings')\n", | |
"axes[1].barh(width=rec_value, y=[i for i in range(len(skill))])\n", | |
"fig.suptitle('Results of optimal performance')\n", | |
"plotly_fig = tls.mpl_to_plotly(fig)\n", | |
"py.iplot(plotly_fig, filename='weakestLinkOptimal')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\" seamless=\"seamless\" src=\"https://plot.ly/~kevinrmcelwee/63.embed\" height=\"800px\" width=\"800px\"></iframe>" | |
], | |
"text/plain": [ | |
"<plotly.tools.PlotlyDisplay object>" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"data = [go.Contour(z=results, ncontours=25)]\n", | |
"layout = go.Layout(\n", | |
" title=\"Contour Map of Winnings\", \n", | |
" xaxis={'title':'number of turns player waits'}, \n", | |
" yaxis={'title':'total winnings'},\n", | |
" autosize=False,\n", | |
" width=800,\n", | |
" height=800,\n", | |
")\n", | |
"\n", | |
"fig = go.Figure(data=data, layout=layout)\n", | |
"py.iplot(fig, filename='weakestLinkCountour')" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"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.6.8" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment