Tweaked day 1 solutions
[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": 2,
54 "metadata": {},
55 "outputs": [
56 {
57 "data": {
58 "text/plain": [
59 "[['dda7d369', '1546', 'Uzupis', '21'],\n",
60 " ['68022753', '1239', 'Mamula', '21'],\n",
61 " ['b261dbd1cef', '996', 'Holmegaard', '21']]"
62 ]
63 },
64 "execution_count": 2,
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:\n",
73 " holidays.append(hol_line.split())\n",
74 " \n",
75 "holidays[:3]"
76 ]
77 },
78 {
79 "cell_type": "code",
80 "execution_count": 3,
81 "metadata": {},
82 "outputs": [
83 {
84 "data": {
85 "text/plain": [
86 "[['dda7d369', '1546', 'Uzupis', '21'],\n",
87 " ['68022753', '1239', 'Mamula', '21'],\n",
88 " ['b261dbd1cef', '996', 'Holmegaard', '21']]"
89 ]
90 },
91 "execution_count": 3,
92 "metadata": {},
93 "output_type": "execute_result"
94 }
95 ],
96 "source": [
97 "holidays = [line.split() for line in open('01-holidays.txt')]\n",
98 " \n",
99 "holidays[:3]"
100 ]
101 },
102 {
103 "cell_type": "code",
104 "execution_count": 13,
105 "metadata": {},
106 "outputs": [
107 {
108 "data": {
109 "text/plain": [
110 "59"
111 ]
112 },
113 "execution_count": 13,
114 "metadata": {},
115 "output_type": "execute_result"
116 }
117 ],
118 "source": [
119 "affordable_holidays = []\n",
120 "for h in holidays:\n",
121 " if int(h[1]) <= 1200:\n",
122 " affordable_holidays.append(h)\n",
123 "\n",
124 "len(affordable_holidays)"
125 ]
126 },
127 {
128 "cell_type": "code",
129 "execution_count": 5,
130 "metadata": {},
131 "outputs": [
132 {
133 "data": {
134 "text/plain": [
135 "59"
136 ]
137 },
138 "execution_count": 5,
139 "metadata": {},
140 "output_type": "execute_result"
141 }
142 ],
143 "source": [
144 "affordable_holidays = [h for h in holidays if int(h[1]) <= 1200]\n",
145 "len(affordable_holidays)"
146 ]
147 },
148 {
149 "cell_type": "code",
150 "execution_count": 14,
151 "metadata": {},
152 "outputs": [
153 {
154 "data": {
155 "text/plain": [
156 "124"
157 ]
158 },
159 "execution_count": 14,
160 "metadata": {},
161 "output_type": "execute_result"
162 }
163 ],
164 "source": [
165 "len(holidays)"
166 ]
167 },
168 {
169 "cell_type": "markdown",
170 "metadata": {},
171 "source": [
172 "### Smart-alec one-line solution"
173 ]
174 },
175 {
176 "cell_type": "code",
177 "execution_count": 4,
178 "metadata": {},
179 "outputs": [
180 {
181 "data": {
182 "text/plain": [
183 "59"
184 ]
185 },
186 "execution_count": 4,
187 "metadata": {},
188 "output_type": "execute_result"
189 }
190 ],
191 "source": [
192 "sum(1 for h in open('01-holidays.txt') if int(h.split()[1]) <= 1200)"
193 ]
194 },
195 {
196 "cell_type": "markdown",
197 "metadata": {},
198 "source": [
199 "# Part 2\n",
200 "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",
201 "\n",
202 "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",
203 "\n",
204 "Assume all holidays have a relative value of 1, apart from these destinations.\n",
205 "\n",
206 "| Destination | Score |\n",
207 "|-------------|-------|\n",
208 "| Almaty | 2.0 |\n",
209 "| Brorfelde | 0.9 |\n",
210 "| Estacada | 0.4 |\n",
211 "| Jayuya | 0.6 |\n",
212 "| Karlukovo | 2.2 |\n",
213 "| Morgantown | 2.9 |\n",
214 "| Nordkapp | 1.5 |\n",
215 "| Nullarbor | 2.2 |\n",
216 "| Puente-Laguna-Garzonkuala-Penyu | 0.4 |\n",
217 "| Uzupis | 0.9 |\n",
218 "\n",
219 "## Example\n",
220 "\n",
221 "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",
222 "\n",
223 "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",
224 "\n",
225 "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",
226 "\n",
227 "The best value affordable holiday is the trip to Stonnington Island, with $\\frac{14}{1284} = 0.0193$ nights per pound."
228 ]
229 },
230 {
231 "cell_type": "code",
232 "execution_count": 16,
233 "metadata": {
234 "collapsed": true
235 },
236 "outputs": [],
237 "source": [
238 "destination_values = {'Almaty': 2.0, 'Brorfelde': 0.9, 'Estacada': 0.4, 'Jayuya': 0.6, 'Karlukovo': 2.2, \n",
239 " 'Morgantown': 2.9,'Nordkapp': 1.5, 'Nullarbor': 2.2, \n",
240 " 'Puente-Laguna-Garzonkuala-Penyu': 0.4, 'Uzupis': 0.9}"
241 ]
242 },
243 {
244 "cell_type": "code",
245 "execution_count": 17,
246 "metadata": {
247 "collapsed": true
248 },
249 "outputs": [],
250 "source": [
251 "def value_of_destination(name):\n",
252 " if name in destination_values:\n",
253 " return destination_values[name]\n",
254 " else:\n",
255 " return 1"
256 ]
257 },
258 {
259 "cell_type": "code",
260 "execution_count": 18,
261 "metadata": {
262 "collapsed": true
263 },
264 "outputs": [],
265 "source": [
266 "def value_of_holiday(holiday):\n",
267 " hid, cost, destination, duration = tuple(holiday)\n",
268 " value = value_of_destination(destination) * float(duration) / int(cost)\n",
269 " return value"
270 ]
271 },
272 {
273 "cell_type": "code",
274 "execution_count": 19,
275 "metadata": {},
276 "outputs": [
277 {
278 "data": {
279 "text/plain": [
280 "'ee064e1e2ea'"
281 ]
282 },
283 "execution_count": 19,
284 "metadata": {},
285 "output_type": "execute_result"
286 }
287 ],
288 "source": [
289 "best_holiday = ''\n",
290 "best_value = 0\n",
291 "\n",
292 "for h in affordable_holidays:\n",
293 " if value_of_holiday(h) > best_value:\n",
294 " best_value = value_of_holiday(h)\n",
295 " best_holiday = h[0]\n",
296 " \n",
297 "best_holiday"
298 ]
299 },
300 {
301 "cell_type": "markdown",
302 "metadata": {},
303 "source": [
304 "## Smart-alec solution"
305 ]
306 },
307 {
308 "cell_type": "code",
309 "execution_count": 20,
310 "metadata": {},
311 "outputs": [
312 {
313 "data": {
314 "text/plain": [
315 "'ee064e1e2ea'"
316 ]
317 },
318 "execution_count": 20,
319 "metadata": {},
320 "output_type": "execute_result"
321 }
322 ],
323 "source": [
324 "# Right answer\n",
325 "max(affordable_holidays, key=value_of_holiday)[0]"
326 ]
327 },
328 {
329 "cell_type": "code",
330 "execution_count": 21,
331 "metadata": {},
332 "outputs": [
333 {
334 "data": {
335 "text/plain": [
336 "'c86e2e5826'"
337 ]
338 },
339 "execution_count": 21,
340 "metadata": {},
341 "output_type": "execute_result"
342 }
343 ],
344 "source": [
345 "# Answer if you don't filter by affordability\n",
346 "max(holidays, key=value_of_holiday)[0]"
347 ]
348 },
349 {
350 "cell_type": "code",
351 "execution_count": 23,
352 "metadata": {},
353 "outputs": [
354 {
355 "data": {
356 "text/plain": [
357 "'f60e203aaaf9'"
358 ]
359 },
360 "execution_count": 23,
361 "metadata": {},
362 "output_type": "execute_result"
363 }
364 ],
365 "source": [
366 "# Answer if you don't scale by perceived value\n",
367 "max(affordable_holidays, key=lambda h: float(h[3]) / float(h[1]))[0]"
368 ]
369 },
370 {
371 "cell_type": "code",
372 "execution_count": 22,
373 "metadata": {},
374 "outputs": [
375 {
376 "data": {
377 "text/plain": [
378 "'f60e203aaaf9'"
379 ]
380 },
381 "execution_count": 22,
382 "metadata": {},
383 "output_type": "execute_result"
384 }
385 ],
386 "source": [
387 "# Answer if you don't scale by perceived value, AND don't filter by affordability\n",
388 "max(holidays, key=lambda h: float(h[3]) / float(h[1]))[0]"
389 ]
390 }
391 ],
392 "metadata": {
393 "kernelspec": {
394 "display_name": "Python 3",
395 "language": "python",
396 "name": "python3"
397 },
398 "language_info": {
399 "codemirror_mode": {
400 "name": "ipython",
401 "version": 3
402 },
403 "file_extension": ".py",
404 "mimetype": "text/x-python",
405 "name": "python",
406 "nbconvert_exporter": "python",
407 "pygments_lexer": "ipython3",
408 "version": "3.5.2+"
409 }
410 },
411 "nbformat": 4,
412 "nbformat_minor": 2
413 }