df02700d400d03ef34215d2097fc5cf347616d9e
[ou-summer-of-code-2017.git] / 01-ticket-prices / ticket-pricing-solution.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# Ticket pricing\n",
8 "\n",
9 "You've been shopping around for a holiday package deal and its time to make your choice of which deal to go with. The file [01-holidays.txt](01-holidays.txt) contains a summary of your investigations. \n",
10 "\n",
11 "It's a simple text file, with one possible holiday package per line.\n",
12 "\n",
13 "Each line has four fields, separated by spaces. They are:\n",
14 "* The deal ID, from the price comparison website you found it.\n",
15 "* The holiday price, in whole pounds.\n",
16 "* The location of the holiday, always a single word.\n",
17 "* The number of nights you'd be staying. \n",
18 "\n",
19 "For example, the data file might look like this:\n",
20 "\n",
21 "```\n",
22 "db61bb90 769 Morgantown 3\n",
23 "202c898b5f 1284 Morgantown 21\n",
24 "def36ffcd 1514 Giessenmestia 21\n",
25 "389018bd0707 1052 Estacada 21\n",
26 "a487c4270 782 Geoje-Si 14\n",
27 "6caf2584a55 724 Stonington-Island 14\n",
28 "199608abc5 1209 Nordkapp 21\n",
29 "```"
30 ]
31 },
32 {
33 "cell_type": "markdown",
34 "metadata": {},
35 "source": [
36 "## Part 1\n",
37 "You have a budget of £1200. How many of the holidays can you afford?\n",
38 "\n",
39 "Given the example data above, you could afford four of the holidays: the trips to Estacada, Geoje-Si and Stonnington-Island, and the three-day trip to Morgantown. \n",
40 "\n",
41 "The 21 day trip to Morgantown and the trips to Giessenmestia and Nordkapp are all too expensive."
42 ]
43 },
44 {
45 "cell_type": "markdown",
46 "metadata": {},
47 "source": [
48 "### Solution"
49 ]
50 },
51 {
52 "cell_type": "code",
53 "execution_count": 1,
54 "metadata": {},
55 "outputs": [
56 {
57 "data": {
58 "text/plain": [
59 "[['07ea553e', '1348', 'Zhangye-Shi', '14'],\n",
60 " ['02d4b258b8a', '1152', 'Estacada', '3'],\n",
61 " ['d29a0551504e', '1210', 'Zhangye-Shi', '7']]"
62 ]
63 },
64 "execution_count": 1,
65 "metadata": {},
66 "output_type": "execute_result"
67 }
68 ],
69 "source": [
70 "holidays = []\n",
71 "with open('01-holidays.txt') as f:\n",
72 " for hol_line in f.readlines():\n",
73 " holidays.append(hol_line.split())\n",
74 " \n",
75 "holidays[:3]"
76 ]
77 },
78 {
79 "cell_type": "code",
80 "execution_count": 2,
81 "metadata": {},
82 "outputs": [
83 {
84 "data": {
85 "text/plain": [
86 "66"
87 ]
88 },
89 "execution_count": 2,
90 "metadata": {},
91 "output_type": "execute_result"
92 }
93 ],
94 "source": [
95 "affordable_holidays = []\n",
96 "for h in holidays:\n",
97 " if int(h[1]) <= 1200:\n",
98 " affordable_holidays.append(h)\n",
99 "\n",
100 "len(affordable_holidays)"
101 ]
102 },
103 {
104 "cell_type": "markdown",
105 "metadata": {},
106 "source": [
107 "### Smart-alec one-line solution"
108 ]
109 },
110 {
111 "cell_type": "code",
112 "execution_count": 3,
113 "metadata": {},
114 "outputs": [
115 {
116 "data": {
117 "text/plain": [
118 "66"
119 ]
120 },
121 "execution_count": 3,
122 "metadata": {},
123 "output_type": "execute_result"
124 }
125 ],
126 "source": [
127 "sum(1 for h in open('01-holidays.txt').readlines() if int(h.split()[1]) <= 1200)"
128 ]
129 },
130 {
131 "cell_type": "markdown",
132 "metadata": {},
133 "source": [
134 "# Part 2\n",
135 "You don't just want _a_ holiday. You want the _best_ holiday. What is the code of the holiday which would give you the best value?\n",
136 "\n",
137 "The \"value\" of a holiday is the duration per pound. Because some destinations are better than others, you'll want to scale the value for some locations. For instance, a night in Timbuktu is worth three times as much as a holiday in Bletchley.\n",
138 "\n",
139 "Assume all holidays have a relative value of 1, apart from these destinations.\n",
140 "\n",
141 "| Destination | Score |\n",
142 "|-------------|-------|\n",
143 "| Almaty | 2.0 |\n",
144 "| Brorfelde | 0.9 |\n",
145 "| Estacada | 0.4 |\n",
146 "| Jayuya | 0.6 |\n",
147 "| Karlukovo | 2.2 |\n",
148 "| Morgantown | 2.9 |\n",
149 "| Nordkapp | 1.5 |\n",
150 "| Nullarbor | 2.2 |\n",
151 "| Puente-Laguna-Garzonkuala-Penyu | 0.4 |\n",
152 "| Uzupis | 0.9 |\n",
153 "\n",
154 "## Example\n",
155 "\n",
156 "Given the holiday list above, the holiday to Geoje-Si (with the standard weighting of 1) has a value of $\\frac{14}{782} = 0.0179$ nights per pound. \n",
157 "\n",
158 "The trip to Estacada looks promising, at $\\frac{21}{1052} = 0.0200$ nights per pound. Unfortunately, the weighting for Estacada is low, to the adjusted cost is $0.4 \\times \\frac{21}{1052} = 0.00798$ nights per pound.\n",
159 "\n",
160 "The best value holiday is the 21 day trip to Morgantown, with a value of $2.9 \\times \\frac{21}{1284} = 0.0474$ nights per pound. Unfortunately, it's unaffordable. \n",
161 "\n",
162 "The best value affordable holiday is the trip to Stonnington Island, with $\\frac{14}{1284} = 0.0193$ nights per pound."
163 ]
164 },
165 {
166 "cell_type": "code",
167 "execution_count": 4,
168 "metadata": {
169 "collapsed": true
170 },
171 "outputs": [],
172 "source": [
173 "destination_values = {'Almaty': 2.0, 'Brorfelde': 0.9, 'Estacada': 0.4, 'Jayuya': 0.6, 'Karlukovo': 2.2, \n",
174 " 'Morgantown': 2.9,'Nordkapp': 1.5, 'Nullarbor': 2.2, \n",
175 " 'Puente-Laguna-Garzonkuala-Penyu': 0.4, 'Uzupis': 0.9}"
176 ]
177 },
178 {
179 "cell_type": "code",
180 "execution_count": 5,
181 "metadata": {
182 "collapsed": true
183 },
184 "outputs": [],
185 "source": [
186 "def value_of_destination(name):\n",
187 " if name in destination_values:\n",
188 " return destination_values[name]\n",
189 " else:\n",
190 " return 1"
191 ]
192 },
193 {
194 "cell_type": "code",
195 "execution_count": 6,
196 "metadata": {
197 "collapsed": true
198 },
199 "outputs": [],
200 "source": [
201 "def value_of_holiday(holiday):\n",
202 " hid, cost, destination, duration = tuple(holiday)\n",
203 " value = value_of_destination(destination) * float(duration) / int(cost)\n",
204 " return value"
205 ]
206 },
207 {
208 "cell_type": "code",
209 "execution_count": 7,
210 "metadata": {},
211 "outputs": [
212 {
213 "data": {
214 "text/plain": [
215 "'cb24efd90'"
216 ]
217 },
218 "execution_count": 7,
219 "metadata": {},
220 "output_type": "execute_result"
221 }
222 ],
223 "source": [
224 "best_holiday = ''\n",
225 "best_value = 0\n",
226 "\n",
227 "for h in affordable_holidays:\n",
228 " if value_of_holiday(h) > best_value:\n",
229 " best_value = value_of_holiday(h)\n",
230 " best_holiday = h[0]\n",
231 " \n",
232 "best_holiday"
233 ]
234 },
235 {
236 "cell_type": "markdown",
237 "metadata": {},
238 "source": [
239 "## Smart-alec solution"
240 ]
241 },
242 {
243 "cell_type": "code",
244 "execution_count": 8,
245 "metadata": {},
246 "outputs": [
247 {
248 "data": {
249 "text/plain": [
250 "'cb24efd90'"
251 ]
252 },
253 "execution_count": 8,
254 "metadata": {},
255 "output_type": "execute_result"
256 }
257 ],
258 "source": [
259 "max(affordable_holidays, key=value_of_holiday)[0]"
260 ]
261 },
262 {
263 "cell_type": "code",
264 "execution_count": null,
265 "metadata": {
266 "collapsed": true
267 },
268 "outputs": [],
269 "source": []
270 }
271 ],
272 "metadata": {
273 "kernelspec": {
274 "display_name": "Python 3",
275 "language": "python",
276 "name": "python3"
277 },
278 "language_info": {
279 "codemirror_mode": {
280 "name": "ipython",
281 "version": 3
282 },
283 "file_extension": ".py",
284 "mimetype": "text/x-python",
285 "name": "python",
286 "nbconvert_exporter": "python",
287 "pygments_lexer": "ipython3",
288 "version": "3.5.2+"
289 }
290 },
291 "nbformat": 4,
292 "nbformat_minor": 2
293 }