Fixed typo
[advent-of-code-15.git] / advent21.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 133,
6 "metadata": {
7 "collapsed": true
8 },
9 "outputs": [],
10 "source": [
11 "import collections\n",
12 "import itertools"
13 ]
14 },
15 {
16 "cell_type": "code",
17 "execution_count": 134,
18 "metadata": {
19 "collapsed": true
20 },
21 "outputs": [],
22 "source": [
23 "def player_wins_fight(player, boss, verbose=False):\n",
24 " boss_hp = boss['hp']\n",
25 " pc_hp = player['hp']\n",
26 " while pc_hp > 0 and boss_hp > 0:\n",
27 " boss_hp -= max(player['damage'] - boss['armour'], 1)\n",
28 " pc_hp -= max(boss['damage'] - player['armour'], 1)\n",
29 " if verbose:\n",
30 " print('PC:', player['hp'], ' . Boss:', boss_hp)\n",
31 " if boss_hp <= 0:\n",
32 " return True\n",
33 " else:\n",
34 " return False"
35 ]
36 },
37 {
38 "cell_type": "code",
39 "execution_count": 135,
40 "metadata": {
41 "collapsed": false
42 },
43 "outputs": [
44 {
45 "data": {
46 "text/plain": [
47 "True"
48 ]
49 },
50 "execution_count": 135,
51 "metadata": {},
52 "output_type": "execute_result"
53 }
54 ],
55 "source": [
56 "pc = {'hp': 8, 'damage': 5, 'armour': 5}\n",
57 "boss = {'hp': 12, 'damage': 7, 'armour': 2}\n",
58 "player_wins_fight(pc, boss)"
59 ]
60 },
61 {
62 "cell_type": "code",
63 "execution_count": 136,
64 "metadata": {
65 "collapsed": false
66 },
67 "outputs": [
68 {
69 "data": {
70 "text/plain": [
71 "({'armour': 5, 'damage': 5, 'hp': 8}, {'armour': 2, 'damage': 7, 'hp': 12})"
72 ]
73 },
74 "execution_count": 136,
75 "metadata": {},
76 "output_type": "execute_result"
77 }
78 ],
79 "source": [
80 "pc, boss"
81 ]
82 },
83 {
84 "cell_type": "code",
85 "execution_count": 137,
86 "metadata": {
87 "collapsed": false
88 },
89 "outputs": [
90 {
91 "data": {
92 "text/plain": [
93 "{'armour': 2, 'damage': 8, 'hp': 100}"
94 ]
95 },
96 "execution_count": 137,
97 "metadata": {},
98 "output_type": "execute_result"
99 }
100 ],
101 "source": [
102 "boss = {}\n",
103 "for l in open('advent21.txt').readlines():\n",
104 " t, v = l.strip().split(': ')\n",
105 " if t == 'Hit Points': \n",
106 " boss['hp'] = int(v)\n",
107 " elif t == 'Armor': \n",
108 " boss['armour'] = int(v)\n",
109 " else:\n",
110 " boss[t.lower()] = int(v)\n",
111 "boss"
112 ]
113 },
114 {
115 "cell_type": "code",
116 "execution_count": 138,
117 "metadata": {
118 "collapsed": true
119 },
120 "outputs": [],
121 "source": [
122 "weapons_s = \"\"\"Dagger 8 4 0\n",
123 "Shortsword 10 5 0\n",
124 "Warhammer 25 6 0\n",
125 "Longsword 40 7 0\n",
126 "Greataxe 74 8 0\"\"\"\n",
127 "\n",
128 "armour_s = \"\"\"Leather 13 0 1\n",
129 "Chainmail 31 0 2\n",
130 "Splintmail 53 0 3\n",
131 "Bandedmail 75 0 4\n",
132 "Platemail 102 0 5\"\"\"\n",
133 "\n",
134 "rings_s = \"\"\"Damage+1 25 1 0\n",
135 "Damage+2 50 2 0\n",
136 "Damage+3 100 3 0\n",
137 "Defense+1 20 0 1\n",
138 "Defense+2 40 0 2\n",
139 "Defense+3 80 0 3\"\"\""
140 ]
141 },
142 {
143 "cell_type": "code",
144 "execution_count": 140,
145 "metadata": {
146 "collapsed": false
147 },
148 "outputs": [],
149 "source": [
150 "def parse_table(table):\n",
151 " d = []\n",
152 " for l in table.split('\\n'):\n",
153 " ls = l.split()\n",
154 " d += [{'name': ls[0].strip(),\n",
155 " 'cost': int(ls[1].strip()), \n",
156 " 'damage': int(ls[2].strip()), \n",
157 " 'armour': int(ls[3].strip()) }]\n",
158 " return d"
159 ]
160 },
161 {
162 "cell_type": "code",
163 "execution_count": 141,
164 "metadata": {
165 "collapsed": false
166 },
167 "outputs": [
168 {
169 "data": {
170 "text/plain": [
171 "([{'armour': 0, 'cost': 8, 'damage': 4, 'name': 'Dagger'},\n",
172 " {'armour': 0, 'cost': 10, 'damage': 5, 'name': 'Shortsword'},\n",
173 " {'armour': 0, 'cost': 25, 'damage': 6, 'name': 'Warhammer'},\n",
174 " {'armour': 0, 'cost': 40, 'damage': 7, 'name': 'Longsword'},\n",
175 " {'armour': 0, 'cost': 74, 'damage': 8, 'name': 'Greataxe'}],\n",
176 " [{'armour': 1, 'cost': 13, 'damage': 0, 'name': 'Leather'},\n",
177 " {'armour': 2, 'cost': 31, 'damage': 0, 'name': 'Chainmail'},\n",
178 " {'armour': 3, 'cost': 53, 'damage': 0, 'name': 'Splintmail'},\n",
179 " {'armour': 4, 'cost': 75, 'damage': 0, 'name': 'Bandedmail'},\n",
180 " {'armour': 5, 'cost': 102, 'damage': 0, 'name': 'Platemail'},\n",
181 " {}],\n",
182 " [{'armour': 0, 'cost': 25, 'damage': 1, 'name': 'Damage+1'},\n",
183 " {'armour': 0, 'cost': 50, 'damage': 2, 'name': 'Damage+2'},\n",
184 " {'armour': 0, 'cost': 100, 'damage': 3, 'name': 'Damage+3'},\n",
185 " {'armour': 1, 'cost': 20, 'damage': 0, 'name': 'Defense+1'},\n",
186 " {'armour': 2, 'cost': 40, 'damage': 0, 'name': 'Defense+2'},\n",
187 " {'armour': 3, 'cost': 80, 'damage': 0, 'name': 'Defense+3'},\n",
188 " {},\n",
189 " {}])"
190 ]
191 },
192 "execution_count": 141,
193 "metadata": {},
194 "output_type": "execute_result"
195 }
196 ],
197 "source": [
198 "weapons = parse_table(weapons_s)\n",
199 "armour = parse_table(armour_s)\n",
200 "armour += [{}]\n",
201 "rings = parse_table(rings_s)\n",
202 "rings += [{}, {}]\n",
203 "weapons, armour, rings"
204 ]
205 },
206 {
207 "cell_type": "code",
208 "execution_count": 142,
209 "metadata": {
210 "collapsed": true
211 },
212 "outputs": [],
213 "source": [
214 "def player(equipment):\n",
215 " player = {'hp': 100, 'damage': 0, 'armour': 0, 'cost': 0, 'name': ''}\n",
216 " for e in equipment:\n",
217 " for s in e:\n",
218 " player[s] += e[s]\n",
219 " return player"
220 ]
221 },
222 {
223 "cell_type": "code",
224 "execution_count": 143,
225 "metadata": {
226 "collapsed": false
227 },
228 "outputs": [
229 {
230 "data": {
231 "text/plain": [
232 "{'armour': 4, 'cost': 217, 'damage': 10, 'hp': 100, 'name': ''}"
233 ]
234 },
235 "execution_count": 143,
236 "metadata": {},
237 "output_type": "execute_result"
238 }
239 ],
240 "source": [
241 "player([{'armour': 0, 'cost': 74, 'damage': 8}, {'armour': 1, 'cost': 13, 'damage': 0},\n",
242 " {'armour': 0, 'cost': 50, 'damage': 2}, {'armour': 3, 'cost': 80, 'damage': 0}])"
243 ]
244 },
245 {
246 "cell_type": "code",
247 "execution_count": 144,
248 "metadata": {
249 "collapsed": false
250 },
251 "outputs": [
252 {
253 "data": {
254 "text/plain": [
255 "840"
256 ]
257 },
258 "execution_count": 144,
259 "metadata": {},
260 "output_type": "execute_result"
261 }
262 ],
263 "source": [
264 "equipment = itertools.chain(\n",
265 " itertools.product(\n",
266 " itertools.combinations(weapons, 1),\n",
267 " itertools.combinations(armour, 1),\n",
268 " itertools.combinations(rings, 2)))\n",
269 "\n",
270 "players = [player(j for i in e for j in i) for e in equipment]\n",
271 "len(players)"
272 ]
273 },
274 {
275 "cell_type": "code",
276 "execution_count": 146,
277 "metadata": {
278 "collapsed": false
279 },
280 "outputs": [
281 {
282 "data": {
283 "text/plain": [
284 "91"
285 ]
286 },
287 "execution_count": 146,
288 "metadata": {},
289 "output_type": "execute_result"
290 }
291 ],
292 "source": [
293 "winner = [p for p in players if not player_wins_fight(p, boss)]\n",
294 "# sorted(winners, key=lambda w: w['cost'])\n",
295 "min(winners, key=lambda w: w['cost'])['cost']"
296 ]
297 },
298 {
299 "cell_type": "markdown",
300 "metadata": {},
301 "source": [
302 "#Part 2"
303 ]
304 },
305 {
306 "cell_type": "code",
307 "execution_count": 149,
308 "metadata": {
309 "collapsed": false
310 },
311 "outputs": [
312 {
313 "data": {
314 "text/plain": [
315 "840"
316 ]
317 },
318 "execution_count": 149,
319 "metadata": {},
320 "output_type": "execute_result"
321 }
322 ],
323 "source": [
324 "equipment = itertools.chain(\n",
325 " itertools.product(\n",
326 " itertools.combinations(weapons, 1),\n",
327 " itertools.combinations(armour, 1),\n",
328 " itertools.combinations(rings, 2)))\n",
329 "\n",
330 "players = [player(j for i in e for j in i) for e in equipment]\n",
331 "len(players)"
332 ]
333 },
334 {
335 "cell_type": "code",
336 "execution_count": 151,
337 "metadata": {
338 "collapsed": false
339 },
340 "outputs": [
341 {
342 "data": {
343 "text/plain": [
344 "158"
345 ]
346 },
347 "execution_count": 151,
348 "metadata": {},
349 "output_type": "execute_result"
350 }
351 ],
352 "source": [
353 "losers = [p for p in players if not player_wins_fight(p, boss)]\n",
354 "# sorted(losers, key=lambda w: w['cost'], reverse=True)\n",
355 "max(losers, key=lambda w: w['cost'])['cost']"
356 ]
357 },
358 {
359 "cell_type": "code",
360 "execution_count": null,
361 "metadata": {
362 "collapsed": true
363 },
364 "outputs": [],
365 "source": []
366 }
367 ],
368 "metadata": {
369 "kernelspec": {
370 "display_name": "Python 3",
371 "language": "python",
372 "name": "python3"
373 },
374 "language_info": {
375 "codemirror_mode": {
376 "name": "ipython",
377 "version": 3
378 },
379 "file_extension": ".py",
380 "mimetype": "text/x-python",
381 "name": "python",
382 "nbconvert_exporter": "python",
383 "pygments_lexer": "ipython3",
384 "version": "3.4.3"
385 }
386 },
387 "nbformat": 4,
388 "nbformat_minor": 0
389 }