From c9390cdb3351a8dba8cb2f36b2118138099ceb08 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Mon, 15 May 2017 16:54:59 +0100 Subject: [PATCH] Problem 1 done --- 01-ticket-prices/01-holidays.txt | 124 ++++ .../ticket-pricing-generator.ipynb | 529 ++++++++++++++++++ .../ticket-pricing-solution.ipynb | 285 ++++++++++ 3 files changed, 938 insertions(+) create mode 100644 01-ticket-prices/01-holidays.txt create mode 100644 01-ticket-prices/ticket-pricing-generator.ipynb create mode 100644 01-ticket-prices/ticket-pricing-solution.ipynb diff --git a/01-ticket-prices/01-holidays.txt b/01-ticket-prices/01-holidays.txt new file mode 100644 index 0000000..f0f2f9b --- /dev/null +++ b/01-ticket-prices/01-holidays.txt @@ -0,0 +1,124 @@ +5f12ce1b86 1192 Sukhumi 14 +0279c8a91b 1008 Estacada 14 +1faea40e9c 1085 Tambon-Pa-Fa 14 +f421c9db0e 1056 Giessenmestia 10 +4d0ae38b17 1173 Mamula 7 +a61861c0ac 1692 Mamula 21 +8917807a68 1364 Parowan 7 +dc16c9b87f 1118 Karlukovo 21 +9e074d106c 887 Hajnowski 7 +25b1f581cf 1350 Tambon-Pa-Fa 14 +18568253ed 1368 Grimsey-Island 21 +5ca507289d 1476 Almaty 21 +90450d21f6 734 Karlukovo 3 +6bf2d26963 945 Sofia 7 +f13de9792c 1258 Aalborg 10 +4c3bd41774 1583 Holmegaard 21 +a211ae5b39 1400 Tubakuba 14 +1ee88b0301 1319 Mamula 14 +908ab2a57b 1394 Gorongosa 14 +7ad1ff45a7 1360 Tubakuba 14 +05949506f4 1599 Nullarbor 14 +5c8ae5d69b 1081 Giessenmestia 14 +93bb91f174 1027 Zhangye-Shi 10 +c1cce289bb 1048 Zhangye-Shi 14 +07ba9b25bb 1317 Mora 3 +557495ff48 1245 Brorfelde 14 +4d91320955 1231 Nordkapp 21 +c3d1a965bf 1564 Zhangye-Shi 14 +905044f0db 1231 Zhangye-Shi 14 +d8c29f025b 850 Uzupis 7 +7d21173587 827 Mamula 21 +7b61f62563 1059 Gorongosa 14 +418c819924 1592 Hajnowski 14 +39ba2e545f 1153 Giessenmestia 14 +a88bcde08f 1200 Geoje-Si 21 +ba97dce538 1334 Luoyang 10 +bfedf47e75 1411 Tambon-Pa-Fa 14 +c75972736e 1360 Tambon-Pa-Fa 10 +a627eacf02 1071 Hajnowski 14 +e5fd4f07f0 1722 Estacada 14 +ecedd5dec7 1298 Holmegaard 21 +82a6d39daf 1304 Hajnowski 14 +df88afc558 1002 Stonington-Island 21 +adfcc87811 1291 Uzupis 10 +ab7c401708 1088 Jayuya 14 +4338ffb0c8 1508 Gorongosa 7 +19137c9d63 1147 Aalborg 21 +e3c8a3457a 938 Sofia 14 +9e17759004 873 Brorfelde 10 +949147682b 1708 Tambon-Pa-Fa 14 +cd8a9e25a5 1331 Parowan 21 +49422ce165 966 Ijsseloog 21 +083f95c140 1277 Stonington-Island 7 +6b0687b1d5 1857 Mora 7 +011a8d05a9 1502 Parowan 21 +905e3adc44 1020 Giessenmestia 7 +dd90450a55 1099 Morgantown 7 +558e37a9cb 1570 Lemnos 7 +adfeed7f5b 930 Luoyang 14 +5b55438fd6 1367 Almaty 10 +d6dbecc2c1 653 Jayuya 21 +c824920d19 916 Giessenmestia 7 +f3e75eb80d 1315 Uzupis 14 +f5b0fa5b52 1351 Mora 21 +1b838183cb 1204 Mamula 14 +d123aee4db 1325 Sofia 7 +d4c5260a30 1238 Brorfelde 7 +15dbab77d7 1124 Nullarbor 21 +4224689a18 1016 Sukhumi 14 +f9dbdcceb5 671 Gorongosa 3 +0cf6e1dcda 1522 Karlukovo 7 +e24cd566b5 1264 Lemnos 7 +f006291b5d 1395 Tubakuba 14 +616b33a8eb 1010 Hajnowski 21 +cc7c78b4d5 828 Tambon-Pa-Fa 14 +748933a4a8 1261 Luoyang 14 +3730f51e7a 1425 Grimsey-Island 3 +0a1786b80e 1336 Brorfelde 14 +7834d83383 1220 Morgantown 14 +921d50e71f 1193 Lemnos 21 +81fc28b097 1224 Lemnos 3 +71271e63c2 936 Morgantown 10 +13272fc146 1063 Zhangye-Shi 10 +999a111ce6 1626 Morgantown 7 +1e6696144b 986 Nullarbor 7 +ea8b6ab428 1256 Nordkapp 3 +f2f4aa7f7f 1223 Lemnos 21 +3b75ed4e29 1483 Holmegaard 14 +227468b611 1280 Grimsey-Island 3 +6316268a67 1240 Holmegaard 14 +ace0751a7e 943 Puente-Laguna-Garzonkuala-Penyu 3 +251b0a29b5 1064 Morgantown 7 +08e358a1a5 1302 Giessenmestia 7 +c4e4b32b01 1117 Grimsey-Island 7 +8b45e786d7 1491 Tubakuba 14 +305c933269 922 Puente-Laguna-Garzonkuala-Penyu 14 +05dc1935d7 1187 Lemnos 21 +31283b3453 794 Jayuya 21 +b08811d0dd 785 Stonington-Island 14 +8108742c66 1137 Jayuya 21 +23a0fefaaa 1129 Tambon-Pa-Fa 14 +0172041cc4 1398 Nullarbor 3 +101f85c2a2 1240 Giessenmestia 21 +e62b71d07b 1121 Aalborg 14 +087a0e8722 1244 Parowan 14 +d3a9a562a0 1252 Giessenmestia 3 +ecddeec9a6 1275 Brorfelde 7 +705d831a04 1411 Almaty 3 +2ed3627cba 1185 Sukhumi 21 +659db7f4ad 1324 Tambon-Pa-Fa 3 +204e527a4b 1465 Giessenmestia 21 +ddb845b71a 1225 Uzupis 7 +ea29fb1ec3 1321 Sukhumi 14 +61d9efb897 1071 Aalborg 14 +e32c91ca86 1130 Puente-Laguna-Garzonkuala-Penyu 14 +164b06af74 1188 Hajnowski 21 +3274507344 1099 Brorfelde 7 +bd18df3cc1 1446 Jayuya 3 +971a59b616 967 Nullarbor 7 +cb3169c441 1132 Almaty 7 +d8ab39ff18 1504 Karlukovo 21 +ad350fa7f1 1373 Geoje-Si 7 +660febfb76 1157 Sukhumi 14 +ec8149cba9 1197 Hajnowski 21 diff --git a/01-ticket-prices/ticket-pricing-generator.ipynb b/01-ticket-prices/ticket-pricing-generator.ipynb new file mode 100644 index 0000000..3d591fd --- /dev/null +++ b/01-ticket-prices/ticket-pricing-generator.ipynb @@ -0,0 +1,529 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import random\n", + "import re\n", + "import uuid" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def cap_after_hyphen(string):\n", + " return re.sub(r'\\-(?P[a-z])', \n", + " lambda m: '-' + m.group('first').upper(), \n", + " string) " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Aalborg',\n", + " 'Nullarbor',\n", + " 'Morgantown',\n", + " 'Estacada',\n", + " 'Almaty',\n", + " 'Tambon-Pa-Fa',\n", + " 'Lemnos',\n", + " 'Sofia',\n", + " 'Puente-Laguna-Garzonkuala-Penyu',\n", + " 'Hajnowski',\n", + " 'Karlukovo',\n", + " 'Mamula',\n", + " 'Stonington-Island',\n", + " 'Grimsey-Island',\n", + " 'Uzupis',\n", + " 'Sukhumi',\n", + " 'Ijsseloog',\n", + " 'Giessenmestia',\n", + " 'Nordkapp',\n", + " 'Gorongosa',\n", + " 'Brorfelde',\n", + " 'Parowan',\n", + " 'Tubakuba',\n", + " 'Geoje-Si',\n", + " 'Mora',\n", + " 'Holmegaard',\n", + " 'Jayuya',\n", + " 'Zhangye-Shi',\n", + " 'Luoyang']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "destination_names = ('Aalborg Nullarbor MORGANTOWN ESTACADA ALMATY TAMBON-PA-FA Lemnos Sofia Puente-Laguna-Garzon' +\n", + "'KUALA-PENYU HAJNOWSKI KARLUKOVO Mamula STONINGTON-ISLAND Grimsey-Island Uzupis SUKHUMI IJsseloog GIESSEN' +\n", + "'MESTIA NORDKAPP GORONGOSA Brorfelde PAROWAN Tubakuba GEOJE-SI MORA HOLMEGAARD JAYUYA ZHANGYE-SHI LUOYANG')\n", + "destination_names = destination_names.lower().split()\n", + "destination_names = [n[0].upper() + n[1:] for n in destination_names]\n", + "destination_names = [cap_after_hyphen(n) for n in destination_names]\n", + "\n", + "destination_names" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Aalborg': 1,\n", + " 'Almaty': 1,\n", + " 'Brorfelde': 1,\n", + " 'Estacada': 1,\n", + " 'Geoje-Si': 1,\n", + " 'Giessenmestia': 1,\n", + " 'Gorongosa': 1,\n", + " 'Grimsey-Island': 1,\n", + " 'Hajnowski': 1,\n", + " 'Holmegaard': 1,\n", + " 'Ijsseloog': 1,\n", + " 'Jayuya': 1,\n", + " 'Karlukovo': 1,\n", + " 'Lemnos': 1,\n", + " 'Luoyang': 1,\n", + " 'Mamula': 1,\n", + " 'Mora': 1,\n", + " 'Morgantown': 1,\n", + " 'Nordkapp': 1,\n", + " 'Nullarbor': 1,\n", + " 'Parowan': 1,\n", + " 'Puente-Laguna-Garzonkuala-Penyu': 1,\n", + " 'Sofia': 1,\n", + " 'Stonington-Island': 1,\n", + " 'Sukhumi': 1,\n", + " 'Tambon-Pa-Fa': 1,\n", + " 'Tubakuba': 1,\n", + " 'Uzupis': 1,\n", + " 'Zhangye-Shi': 1}" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "destination_scores = {n: 1 for n in destination_names}\n", + "destination_scores" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Aalborg': 1,\n", + " 'Almaty': 2.0,\n", + " 'Brorfelde': 0.9,\n", + " 'Estacada': 0.4,\n", + " 'Geoje-Si': 1,\n", + " 'Giessenmestia': 1,\n", + " 'Gorongosa': 1,\n", + " 'Grimsey-Island': 1,\n", + " 'Hajnowski': 1,\n", + " 'Holmegaard': 1,\n", + " 'Ijsseloog': 1,\n", + " 'Jayuya': 0.6,\n", + " 'Karlukovo': 2.2,\n", + " 'Lemnos': 1,\n", + " 'Luoyang': 1,\n", + " 'Mamula': 1,\n", + " 'Mora': 1,\n", + " 'Morgantown': 2.9,\n", + " 'Nordkapp': 1.5,\n", + " 'Nullarbor': 2.2,\n", + " 'Parowan': 1,\n", + " 'Puente-Laguna-Garzonkuala-Penyu': 0.4,\n", + " 'Sofia': 1,\n", + " 'Stonington-Island': 1,\n", + " 'Sukhumi': 1,\n", + " 'Tambon-Pa-Fa': 1,\n", + " 'Tubakuba': 1,\n", + " 'Uzupis': 0.9,\n", + " 'Zhangye-Shi': 1}" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adjust = random.sample(destination_names, 10)\n", + "inc_names = adjust[:5]\n", + "dec_names = adjust[5:]\n", + "for n in inc_names:\n", + " destination_scores[n] = float(random.randint(11, 30)) / 10\n", + "for n in dec_names:\n", + " destination_scores[n] = float(random.randint(3, 9)) / 10 \n", + "destination_scores" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "destination_scores = {'Aalborg': 1, 'Almaty': 2.0, 'Brorfelde': 0.9, 'Estacada': 0.4, 'Geoje-Si': 1,\n", + " 'Giessenmestia': 1, 'Gorongosa': 1, 'Grimsey-Island': 1, 'Hajnowski': 1, 'Holmegaard': 1, 'Ijsseloog': 1,\n", + " 'Jayuya': 0.6, 'Karlukovo': 2.2, 'Lemnos': 1, 'Luoyang': 1, 'Mamula': 1, 'Mora': 1, 'Morgantown': 2.9,\n", + " 'Nordkapp': 1.5, 'Nullarbor': 2.2, 'Parowan': 1, 'Puente-Laguna-Garzonkuala-Penyu': 0.4, 'Sofia': 1,\n", + " 'Stonington-Island': 1, 'Sukhumi': 1, 'Tambon-Pa-Fa': 1, 'Tubakuba': 1, 'Uzupis': 0.9, 'Zhangye-Shi': 1}" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "destination_score_exceptions = {'Almaty': 2.0, 'Brorfelde': 0.9, 'Estacada': 0.4, 'Jayuya': 0.6, 'Karlukovo': 2.2, 'Morgantown': 2.9,\n", + " 'Nordkapp': 1.5, 'Nullarbor': 2.2, 'Puente-Laguna-Garzonkuala-Penyu': 0.4, 'Uzupis': 0.9}" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "| Destination | Score |\n", + "|-------------|-------|\n", + "| Almaty | 2.0 |\n", + "| Brorfelde | 0.9 |\n", + "| Estacada | 0.4 |\n", + "| Jayuya | 0.6 |\n", + "| Karlukovo | 2.2 |\n", + "| Morgantown | 2.9 |\n", + "| Nordkapp | 1.5 |\n", + "| Nullarbor | 2.2 |\n", + "| Puente-Laguna-Garzonkuala-Penyu | 0.4 |\n", + "| Uzupis | 0.9 |\n" + ] + } + ], + "source": [ + "print('| Destination | Score |')\n", + "print('|-------------|-------|')\n", + "for n in sorted(destination_scores):\n", + " if destination_scores[n] != 1:\n", + " print('|', n, '|', destination_scores[n], '|')" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def make_holiday(name=None):\n", + " if not name:\n", + " name = random.choice(destination_names)\n", + " days = random.choice([3, 7, 7, 7, 10, 14, 14, 14, 14, 21, 21])\n", + " price = 0\n", + " for _ in range(4):\n", + " price += random.randint(100, 500)\n", + " hol_id = str(uuid.uuid4())\n", + " return hol_id, price, name, days" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('4615dad7-f5ab-4c9b-8028-b3e5c676ff24', 1046, 'Almaty', 14)" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "make_holiday()" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('3c425201-5538-4a3f-bfd7-1219137c9d63', 1147, 'Aalborg', 21),\n", + " ('5913e357-dc18-49c5-850d-aa0172041cc4', 1398, 'Nullarbor', 3),\n", + " ('bc966859-49ad-4c26-b36e-94251b0a29b5', 1064, 'Morgantown', 7),\n", + " ('ab1d0a54-41bc-4351-beb8-f6e5fd4f07f0', 1722, 'Estacada', 14),\n", + " ('b5efba4e-373d-4a15-b048-8fcb3169c441', 1132, 'Almaty', 7),\n", + " ('bd1ff2b9-5b97-4a13-9d8a-601faea40e9c', 1085, 'Tambon-Pa-Fa', 14),\n", + " ('5b9df004-a8b7-4c28-a27e-21e24cd566b5', 1264, 'Lemnos', 7),\n", + " ('5951de60-9e98-471f-a917-74e3c8a3457a', 938, 'Sofia', 14),\n", + " ('c6a4cad7-cd9a-4e05-bd16-92305c933269',\n", + " 922,\n", + " 'Puente-Laguna-Garzonkuala-Penyu',\n", + " 14),\n", + " ('9527ee0b-4bcd-4a1f-95fd-b3a627eacf02', 1071, 'Hajnowski', 14),\n", + " ('82b6adfb-f09d-420f-bbf9-ea90450d21f6', 734, 'Karlukovo', 3),\n", + " ('7b08192c-5e30-45dc-bb31-2da61861c0ac', 1692, 'Mamula', 21),\n", + " ('5abbe3e4-7d2e-404c-9ce2-27083f95c140', 1277, 'Stonington-Island', 7),\n", + " ('b3f517ca-2a07-427d-8531-81227468b611', 1280, 'Grimsey-Island', 3),\n", + " ('f1fa90d2-0f58-480f-80c0-0fddb845b71a', 1225, 'Uzupis', 7),\n", + " ('330e4f58-31d2-474f-8e23-654224689a18', 1016, 'Sukhumi', 14),\n", + " ('a6837ba1-42aa-488d-b39a-5b49422ce165', 966, 'Ijsseloog', 21),\n", + " ('a7e4161a-0435-4915-961e-8c204e527a4b', 1465, 'Giessenmestia', 21),\n", + " ('633be2e4-a719-496e-9987-d5ea8b6ab428', 1256, 'Nordkapp', 3),\n", + " ('bd83d3e3-6134-4511-918c-a94338ffb0c8', 1508, 'Gorongosa', 7),\n", + " ('05ed4593-3582-4fde-8958-a63274507344', 1099, 'Brorfelde', 7),\n", + " ('b8361d0a-7f23-4491-9450-c28917807a68', 1364, 'Parowan', 7),\n", + " ('dc7f49c2-672e-4abc-a58a-4e8b45e786d7', 1491, 'Tubakuba', 14),\n", + " ('b709a89e-e5c5-4a60-97ca-55ad350fa7f1', 1373, 'Geoje-Si', 7),\n", + " ('18888ae2-e410-4430-87af-1d07ba9b25bb', 1317, 'Mora', 3),\n", + " ('b08ebc25-7d02-4973-8e28-fa3b75ed4e29', 1483, 'Holmegaard', 14),\n", + " ('d3519dde-9a15-4982-b1ed-1dd6dbecc2c1', 653, 'Jayuya', 21),\n", + " ('fa882848-1787-424a-90c3-8593bb91f174', 1027, 'Zhangye-Shi', 10),\n", + " ('21d2fcc8-f528-467d-b0ba-a6748933a4a8', 1261, 'Luoyang', 14)]" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holidays = []\n", + "for n in destination_names:\n", + " holidays += [make_holiday(n)]\n", + "holidays" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "for _ in range(95):\n", + " holidays += [make_holiday()]" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [], + "source": [ + "random.shuffle(holidays)\n", + "with open('01-holidays.txt', 'w') as f:\n", + " for hid, price, name, days in holidays:\n", + " f.write('{} {} {} {}\\n'.format(hid[-10:], price, name, days))" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['5f12ce1b86', '1192', 'Sukhumi', '14'],\n", + " ['0279c8a91b', '1008', 'Estacada', '14'],\n", + " ['1faea40e9c', '1085', 'Tambon-Pa-Fa', '14']]" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with open('01-holidays.txt') as f:\n", + " hols = [h.split() for h in f.readlines()]\n", + "hols[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "assert len(set(h[0] for h in hols)) == len(hols)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('6138068a-3c16-4f7f-8dc6-a1199608abc5', 1209, 'Nordkapp', 21),\n", + " ('eafb15a4-1839-4fb5-be9b-d8389018bd07', 1052, 'Estacada', 21),\n", + " ('ab659b71-347d-45dc-9416-34def36ffc7d', 1514, 'Giessenmestia', 21),\n", + " ('bb8d5034-49ce-483d-ab6c-d16caf2584a5', 724, 'Stonington-Island', 14),\n", + " ('7476b214-8b55-47f6-833e-dfa487c4270a', 782, 'Geoje-Si', 14),\n", + " ('f2ffe169-7cc5-42e1-9b46-8cdb61bb906d', 769, 'Morgantown', 3),\n", + " ('2e6a6d6d-6c08-4021-b99f-05202c898b5f', 1184, 'Morgantown', 21)]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "example_holidays = []\n", + "names = random.sample(destination_score_exceptions.keys(), 2) + random.sample(destination_names, 4)\n", + "names += [names[-1]]\n", + "example_holidays = [make_holiday(n) for n in names]\n", + "example_holidays" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('f2ffe169-7cc5-42e1-9b46-8cdb61bb906d', 769, 'Morgantown', 3),\n", + " ('2e6a6d6d-6c08-4021-b99f-05202c898b5f', 1184, 'Morgantown', 21),\n", + " ('ab659b71-347d-45dc-9416-34def36ffc7d', 1514, 'Giessenmestia', 21),\n", + " ('eafb15a4-1839-4fb5-be9b-d8389018bd07', 1052, 'Estacada', 21),\n", + " ('7476b214-8b55-47f6-833e-dfa487c4270a', 782, 'Geoje-Si', 14),\n", + " ('bb8d5034-49ce-483d-ab6c-d16caf2584a5', 724, 'Stonington-Island', 14),\n", + " ('6138068a-3c16-4f7f-8dc6-a1199608abc5', 1209, 'Nordkapp', 21)]" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "random.shuffle(example_holidays)\n", + "example_holidays" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "example_holidays = [('f2ffe169-7cc5-42e1-9b46-8cdb61bb906d', 769, 'Morgantown', 3),\n", + " ('2e6a6d6d-6c08-4021-b99f-05202c898b5f', 1284, 'Morgantown', 21),\n", + " ('ab659b71-347d-45dc-9416-34def36ffc7d', 1514, 'Giessenmestia', 21),\n", + " ('eafb15a4-1839-4fb5-be9b-d8389018bd07', 1052, 'Estacada', 21),\n", + " ('7476b214-8b55-47f6-833e-dfa487c4270a', 782, 'Geoje-Si', 14),\n", + " ('bb8d5034-49ce-483d-ab6c-d16caf2584a5', 724, 'Stonington-Island', 14),\n", + " ('6138068a-3c16-4f7f-8dc6-a1199608abc5', 1209, 'Nordkapp', 21)]" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "db61bb906d 769 Morgantown 3\n", + "202c898b5f 1284 Morgantown 21\n", + "def36ffc7d 1514 Giessenmestia 21\n", + "389018bd07 1052 Estacada 21\n", + "a487c4270a 782 Geoje-Si 14\n", + "6caf2584a5 724 Stonington-Island 14\n", + "199608abc5 1209 Nordkapp 21\n" + ] + } + ], + "source": [ + "for hid, price, name, days in example_holidays:\n", + " print('{} {} {} {}'.format(hid[-10:], price, name, days))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "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.5.2+" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/01-ticket-prices/ticket-pricing-solution.ipynb b/01-ticket-prices/ticket-pricing-solution.ipynb new file mode 100644 index 0000000..59d7046 --- /dev/null +++ b/01-ticket-prices/ticket-pricing-solution.ipynb @@ -0,0 +1,285 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Ticket pricing\n", + "\n", + "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", + "\n", + "It's a simple text file, with one possible holiday package per line.\n", + "\n", + "Each line has four fields, separated by spaces. They are:\n", + "* The deal ID, from the price comparison website you found it.\n", + "* The holiday price, in whole pounds.\n", + "* The location of the holiday, always a single word.\n", + "* The number of nights you'd be staying. \n", + "\n", + "For example, the data file might look like this:\n", + "\n", + "```\n", + "db61bb906d 769 Morgantown 3\n", + "202c898b5f 1284 Morgantown 21\n", + "def36ffc7d 1514 Giessenmestia 21\n", + "389018bd07 1052 Estacada 21\n", + "a487c4270a 782 Geoje-Si 14\n", + "6caf2584a5 724 Stonington-Island 14\n", + "199608abc5 1209 Nordkapp 21\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Part 1\n", + "You have a budget of £1200. How many of the holidays can you afford?\n", + "\n", + "Given the example data above, you could afford four of the holidays: the 21 day trip to Morgantown and the trips to Giessenmestia and Nordkapp are all too expensive." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solution" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['5f12ce1b86', '1192', 'Sukhumi', '14'],\n", + " ['0279c8a91b', '1008', 'Estacada', '14'],\n", + " ['1faea40e9c', '1085', 'Tambon-Pa-Fa', '14']]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holidays = []\n", + "with open('01-holidays.txt') as f:\n", + " for hol_line in f.readlines():\n", + " holidays.append(hol_line.split())\n", + " \n", + "holidays[:3]" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "57" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "affordable_holidays = []\n", + "for h in holidays:\n", + " if int(h[1]) <= 1200:\n", + " affordable_holidays.append(h)\n", + "\n", + "len(affordable_holidays)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Smart-alec one-line solution" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "57" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(1 for h in open('01-holidays.txt').readlines() if int(h.split()[1]) <= 1200)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Part 2\n", + "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", + "\n", + "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", + "\n", + "Assume all holidays have a relative value of 1, apart from these destinations.\n", + "\n", + "| Destination | Score |\n", + "|-------------|-------|\n", + "| Almaty | 2.0 |\n", + "| Brorfelde | 0.9 |\n", + "| Estacada | 0.4 |\n", + "| Jayuya | 0.6 |\n", + "| Karlukovo | 2.2 |\n", + "| Morgantown | 2.9 |\n", + "| Nordkapp | 1.5 |\n", + "| Nullarbor | 2.2 |\n", + "| Puente-Laguna-Garzonkuala-Penyu | 0.4 |\n", + "| Uzupis | 0.9 |\n", + "\n", + "## Example\n", + "\n", + "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. 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", + "\n", + "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", + "\n", + "The best value affordable holiday is the trip to Stonnington Island, with $\\frac{14}{1284} = 0.0193$ nights per pound." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "destination_values = {'Almaty': 2.0, 'Brorfelde': 0.9, 'Estacada': 0.4, 'Jayuya': 0.6, 'Karlukovo': 2.2, \n", + " 'Morgantown': 2.9,'Nordkapp': 1.5, 'Nullarbor': 2.2, \n", + " 'Puente-Laguna-Garzonkuala-Penyu': 0.4, 'Uzupis': 0.9}" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def value_of_destination(name):\n", + " if name in destination_values:\n", + " return destination_values[name]\n", + " else:\n", + " return 1" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "def value_of_holiday(holiday):\n", + " hid, cost, destination, duration = tuple(holiday)\n", + " value = value_of_destination(destination) * float(duration) / int(cost)\n", + " return value" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'dc16c9b87f'" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "best_holiday = ''\n", + "best_value = 0\n", + "\n", + "for h in affordable_holidays:\n", + " if value_of_holiday(h) > best_value:\n", + " best_value = value_of_holiday(h)\n", + " best_holiday = h[0]\n", + " \n", + "best_holiday" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Smart-alec solution" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'dc16c9b87f'" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "max(affordable_holidays, key=value_of_holiday)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "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.5.2+" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- 2.34.1