{ "cells": [ { "cell_type": "code", "execution_count": 133, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import collections\n", "import itertools" ] }, { "cell_type": "code", "execution_count": 134, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def player_wins_fight(player, boss, verbose=False):\n", " boss_hp = boss['hp']\n", " pc_hp = player['hp']\n", " while pc_hp > 0 and boss_hp > 0:\n", " boss_hp -= max(player['damage'] - boss['armour'], 1)\n", " pc_hp -= max(boss['damage'] - player['armour'], 1)\n", " if verbose:\n", " print('PC:', player['hp'], ' . Boss:', boss_hp)\n", " if boss_hp <= 0:\n", " return True\n", " else:\n", " return False" ] }, { "cell_type": "code", "execution_count": 135, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 135, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pc = {'hp': 8, 'damage': 5, 'armour': 5}\n", "boss = {'hp': 12, 'damage': 7, 'armour': 2}\n", "player_wins_fight(pc, boss)" ] }, { "cell_type": "code", "execution_count": 136, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "({'armour': 5, 'damage': 5, 'hp': 8}, {'armour': 2, 'damage': 7, 'hp': 12})" ] }, "execution_count": 136, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pc, boss" ] }, { "cell_type": "code", "execution_count": 137, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'armour': 2, 'damage': 8, 'hp': 100}" ] }, "execution_count": 137, "metadata": {}, "output_type": "execute_result" } ], "source": [ "boss = {}\n", "for l in open('advent21.txt').readlines():\n", " t, v = l.strip().split(': ')\n", " if t == 'Hit Points': \n", " boss['hp'] = int(v)\n", " elif t == 'Armor': \n", " boss['armour'] = int(v)\n", " else:\n", " boss[t.lower()] = int(v)\n", "boss" ] }, { "cell_type": "code", "execution_count": 138, "metadata": { "collapsed": true }, "outputs": [], "source": [ "weapons_s = \"\"\"Dagger 8 4 0\n", "Shortsword 10 5 0\n", "Warhammer 25 6 0\n", "Longsword 40 7 0\n", "Greataxe 74 8 0\"\"\"\n", "\n", "armour_s = \"\"\"Leather 13 0 1\n", "Chainmail 31 0 2\n", "Splintmail 53 0 3\n", "Bandedmail 75 0 4\n", "Platemail 102 0 5\"\"\"\n", "\n", "rings_s = \"\"\"Damage+1 25 1 0\n", "Damage+2 50 2 0\n", "Damage+3 100 3 0\n", "Defense+1 20 0 1\n", "Defense+2 40 0 2\n", "Defense+3 80 0 3\"\"\"" ] }, { "cell_type": "code", "execution_count": 140, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def parse_table(table):\n", " d = []\n", " for l in table.split('\\n'):\n", " ls = l.split()\n", " d += [{'name': ls[0].strip(),\n", " 'cost': int(ls[1].strip()), \n", " 'damage': int(ls[2].strip()), \n", " 'armour': int(ls[3].strip()) }]\n", " return d" ] }, { "cell_type": "code", "execution_count": 141, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "([{'armour': 0, 'cost': 8, 'damage': 4, 'name': 'Dagger'},\n", " {'armour': 0, 'cost': 10, 'damage': 5, 'name': 'Shortsword'},\n", " {'armour': 0, 'cost': 25, 'damage': 6, 'name': 'Warhammer'},\n", " {'armour': 0, 'cost': 40, 'damage': 7, 'name': 'Longsword'},\n", " {'armour': 0, 'cost': 74, 'damage': 8, 'name': 'Greataxe'}],\n", " [{'armour': 1, 'cost': 13, 'damage': 0, 'name': 'Leather'},\n", " {'armour': 2, 'cost': 31, 'damage': 0, 'name': 'Chainmail'},\n", " {'armour': 3, 'cost': 53, 'damage': 0, 'name': 'Splintmail'},\n", " {'armour': 4, 'cost': 75, 'damage': 0, 'name': 'Bandedmail'},\n", " {'armour': 5, 'cost': 102, 'damage': 0, 'name': 'Platemail'},\n", " {}],\n", " [{'armour': 0, 'cost': 25, 'damage': 1, 'name': 'Damage+1'},\n", " {'armour': 0, 'cost': 50, 'damage': 2, 'name': 'Damage+2'},\n", " {'armour': 0, 'cost': 100, 'damage': 3, 'name': 'Damage+3'},\n", " {'armour': 1, 'cost': 20, 'damage': 0, 'name': 'Defense+1'},\n", " {'armour': 2, 'cost': 40, 'damage': 0, 'name': 'Defense+2'},\n", " {'armour': 3, 'cost': 80, 'damage': 0, 'name': 'Defense+3'},\n", " {},\n", " {}])" ] }, "execution_count": 141, "metadata": {}, "output_type": "execute_result" } ], "source": [ "weapons = parse_table(weapons_s)\n", "armour = parse_table(armour_s)\n", "armour += [{}]\n", "rings = parse_table(rings_s)\n", "rings += [{}, {}]\n", "weapons, armour, rings" ] }, { "cell_type": "code", "execution_count": 142, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def player(equipment):\n", " player = {'hp': 100, 'damage': 0, 'armour': 0, 'cost': 0, 'name': ''}\n", " for e in equipment:\n", " for s in e:\n", " player[s] += e[s]\n", " return player" ] }, { "cell_type": "code", "execution_count": 143, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{'armour': 4, 'cost': 217, 'damage': 10, 'hp': 100, 'name': ''}" ] }, "execution_count": 143, "metadata": {}, "output_type": "execute_result" } ], "source": [ "player([{'armour': 0, 'cost': 74, 'damage': 8}, {'armour': 1, 'cost': 13, 'damage': 0},\n", " {'armour': 0, 'cost': 50, 'damage': 2}, {'armour': 3, 'cost': 80, 'damage': 0}])" ] }, { "cell_type": "code", "execution_count": 144, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "840" ] }, "execution_count": 144, "metadata": {}, "output_type": "execute_result" } ], "source": [ "equipment = itertools.chain(\n", " itertools.product(\n", " itertools.combinations(weapons, 1),\n", " itertools.combinations(armour, 1),\n", " itertools.combinations(rings, 2)))\n", "\n", "players = [player(j for i in e for j in i) for e in equipment]\n", "len(players)" ] }, { "cell_type": "code", "execution_count": 146, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "91" ] }, "execution_count": 146, "metadata": {}, "output_type": "execute_result" } ], "source": [ "winner = [p for p in players if not player_wins_fight(p, boss)]\n", "# sorted(winners, key=lambda w: w['cost'])\n", "min(winners, key=lambda w: w['cost'])['cost']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#Part 2" ] }, { "cell_type": "code", "execution_count": 149, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "840" ] }, "execution_count": 149, "metadata": {}, "output_type": "execute_result" } ], "source": [ "equipment = itertools.chain(\n", " itertools.product(\n", " itertools.combinations(weapons, 1),\n", " itertools.combinations(armour, 1),\n", " itertools.combinations(rings, 2)))\n", "\n", "players = [player(j for i in e for j in i) for e in equipment]\n", "len(players)" ] }, { "cell_type": "code", "execution_count": 151, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "158" ] }, "execution_count": 151, "metadata": {}, "output_type": "execute_result" } ], "source": [ "losers = [p for p in players if not player_wins_fight(p, boss)]\n", "# sorted(losers, key=lambda w: w['cost'], reverse=True)\n", "max(losers, key=lambda w: w['cost'])['cost']" ] }, { "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.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }