Day 22
authorNeil Smith <neil.git@njae.me.uk>
Tue, 22 Dec 2015 12:01:35 +0000 (12:01 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Tue, 22 Dec 2015 12:01:35 +0000 (12:01 +0000)
SIGNED.md
advent-of-code-22.html [new file with mode: 0644]
advent22.ipynb [new file with mode: 0644]

index 851166dfa45e76e8728f59c317b76203f0839ae4..8335e78d7b8b0a58a75dec3b862cae68dca6c429 100644 (file)
--- a/SIGNED.md
+++ b/SIGNED.md
@@ -3,19 +3,19 @@
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
-iQIcBAABCAAGBQJWeCUWAAoJEJPB2e07PgbqroEP/jpfpm2kXw0ZV1GzzKJK/c7P
-og/ruaCLWUn08iPv325GfjA8KCycxsFL6slGN4c66+zqveTIa+dHpabgepQHSdlJ
-FfRDR227eJMLHYF5LrsRQBXj0nD5HMEHXCcdkQPBzUpVTEO6YSsh9TRR1xS/FGf4
-zsbmd7FEGxW9A2VfX9CQtCLLrkIgJrvmceYxSXFRj5XTi3PbTuoba5zq6YP/CJh+
-XtKQirOUnsXqQ5oXJy/P6bGBsmeIZqkuVo4GRVQwo1G+MnX+j6sp/tY/Ft4I5vHd
-6K5G7lPTHYKYyUKNSelJQWZf50PdylTHYKmnkgPxcMepbESPhoAjIBUJOgT+xXq+
-KIMIcPSapAq6fxUWqz8Hi/Q8v0AubvENSjMoI+jwtOAIrKjqHbT1MfWkkdw/dwCw
-7PQQoU92JWgzptVmdr2OebD1vtUJvoxewHTx4LJrbEcYnE8HrLGfsUxGb+3BdSnQ
-Wpsr2iQkbkTMoTrK4fL5ZxtpeV6WJbhVrLFW2EJBTURz0TxrLdFPEUhReXDMNZi0
-LMT+170uRfx4OYZJsvUX7MO2XVgA0+UcBG1MdSz6vGmU9aCIwIscMs8enpjcCSVT
-XMoYU9HEQ6gjEM93zpRefyFYE3z9FzEQJFHVG2gHtkwRYSYCqtHocv8/MZlItz7V
-NW0resJihpsHglTpz43r
-=wiY6
+iQIcBAABCAAGBQJWeTulAAoJEJPB2e07PgbqQswP/0s/iRr+GK90BD6KAbd3ni5J
+Q0ih6b1dWRtLkpBBGzajjlKFt9xoygVjV2CjiH/f2bYH+GJQToT3QBOTRGr+7lC1
+s9UhGmFkHvZC9B2bG9Y/5D15/LCZFONMWJ23HyfIMKUNY4nX5zPf0zje7wbkSj1h
+jdZBrTS9I2UVrA6JT5beKUy0m8fih+WpdlsIV+fbc3TmXgRNwJ5gTtVg8vV2H3SY
+X8cZOYfV2cnhqQxqRclRdncypZNcpRC1vyLja2imchHVaDOB741LD42EZi6gOidH
+4WhlROqWDfdRZI4/Xk4Ugpq33OyjK95Ag75jOX1tt2vUYouZlHortIZArzjT29R/
+nR2F1tY+r8zwy6x03YKtb/bWn1zbgzp8XWFKl6qwDIMOuQEJru8u7foREJRAcESt
+A7PaOpy1YGD908/1Bc1vwvdWenUKlviRULWJoQUuCGmAkI2Ri9CfEEZxcK7pXmZl
+Kkj47XnXLXz+jtBiGG0aj+dt6wbKBOqbXY7eU3CZW5zInQAhEp01I4jcAFTIeuE8
+0Kco/OeDiocDshPfjBLhffakipP9J5bmg8fiIEAU2p+d/4nYmH5neoVxq1WXrSa6
+p6CCTU5DVmueiDg9Ohi+597vD1ylXYEAfzbQaWiQj2N/6Ghe1qwdRYV9omX2l2Wo
+jay9FFBiKYx5GtYn86O3
+=qQcY
 -----END PGP SIGNATURE-----
 
 ```
@@ -55,6 +55,7 @@ size    exec  file                        contents
 7580            advent-of-code-19.html    9cd3b0a1a5a1dc658c09b46ba9624312622ac5cf46fffcaccbeea661b11c577e
 6387            advent-of-code-20.html    3ec26a7cfb58a168b62781f097ebdb71ae3224cadde49588463370faaa3d33f9
 7780            advent-of-code-21.html    877675e47121bd4812ab461fd7cd6124c397669a5e6f35c3f19b023728976970
+10190           advent-of-code-22.html    cb57ad829bd31e59807f3f0ecc95c603eb85b2d9f9e5cbf9432e80283b689298
 109395          advent-of-code.ipynb      7292eeb9a8019f6931037c70105ab96bf691074dbe963736b6429cb4d4373f51
 25607           advent01.ipynb            c33ad39a77803a6870dd74998da98e3bb9c2c2db37c34167b330a01d663717e7
 7001            advent01.txt              79312922877bdedd09ce0886a42b3d7f7ed092e2218579fb7d6ac1cb38cedebe
@@ -95,6 +96,7 @@ size    exec  file                        contents
 3377            advent20.ipynb            be9db2beee6805ac9db9f2dc145abba3275964e36e21580122bacd8436777a30
 9373            advent21.ipynb            70f49b67c911f9316c6be1404b57c76bd0b8aca94e16dd6fc1e5b39d3442b2b4
 35              advent21.txt              6c4c3bcec0bf45ee485c7595a6a5eb2ad7722bdecf275780e1cdb9993eb931d8
+21424           advent22.ipynb            8b8aac9e511209cba4637523266f00f40be7ac70eec6d1f4dd0d0b50cb64dd3f
 ```
 
 #### Ignore
diff --git a/advent-of-code-22.html b/advent-of-code-22.html
new file mode 100644 (file)
index 0000000..b115c1f
--- /dev/null
@@ -0,0 +1,235 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 22 - Advent of Code</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" type="text/css" href="/static/style.css?3"/>
+<link rel="shortcut icon" href="/favicon.ico?2"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  You do risk spoiling a few
+surprises for yourself, though.  Best to play the normal way and discover
+everything as it was intended, I think.  The best surprises don't even appear
+in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not Google, and I can only take
+so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, ads, social media),
+I built the whole thing myself, including the design, animations, prose, and
+all of the puzzles.
+
+The puzzles probably took the longest; the easiest ones were around 45 minutes
+each, but the harder ones took 2-3 hours, some even longer than that. A lot of
+effort went into building this thing - I hope you're enjoying playing it as
+much as I enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><h1><a href="/">Advent of Code</a></h1><div class="user">Neil Smith <span class="star-count">44*</span></div><nav><ul><li><a href="/about">[About]</a></li><li><a href="/stats">[Stats]</a></li><li><a href="/leaderboard">[Leaderboard]</a></li><li><a href="/settings">[Settings]</a></li><li><a href="/auth/logout">[Log out]</a></li></ul></nav></header>
+
+<div id="ad">
+<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- Advent of Code Wide Skyscraper -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:160px;height:600px"
+     data-ad-client="ca-pub-9420604735624631"
+     data-ad-slot="8014013294"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script>
+</div><!--/ad-->
+
+<main>
+<article class="day-desc"><h2>--- Day 22: Wizard Simulator 20XX ---</h2><p>Little Henry Case decides that defeating bosses with <a href="/day/21">swords and stuff</a> is boring.  Now he's playing the game with a <span title="Being a !@#$% Sorcerer.">wizard</span>.  Of course, he gets stuck on another boss and needs your help again.</p>
+<p>In this version, combat still proceeds with the player and the boss taking alternating turns.  The player still goes first.  Now, however, you don't get any equipment; instead, you must choose one of your spells to cast.  The first character at or below <code>0</code> hit points loses.</p>
+<p>Since you're a wizard, you don't get to wear armor, and you can't attack normally.  However, since you do <em>magic damage</em>, your opponent's armor is ignored, and so the boss effectively has zero armor as well.  As before, if armor (from a spell, in this case) would reduce damage below <code>1</code>, it becomes <code>1</code> instead - that is, the boss' attacks always deal at least <code>1</code> damage.</p>
+<p>On each of your turns, you must select one of your spells to cast.  If you cannot afford to cast any spell, you lose.  Spells cost <em>mana</em>; you start with <em>500</em> mana, but have no maximum limit.  You must have enough mana to cast a spell, and its cost is immediately deducted when you cast it.  Your spells are Magic Missile, Drain, Shield, Poison, and Recharge.</p>
+<ul>
+<li><em>Magic Missile</em> costs <code>53</code> mana.  It instantly does <code>4</code> damage.</li>
+<li><em>Drain</em> costs <code>73</code> mana.  It instantly does <code>2</code> damage and heals you for <code>2</code> hit points.</li>
+<li><em>Shield</em> costs <code>113</code> mana.  It starts an <em>effect</em> that lasts for <code>6</code> turns.  While it is active, your armor is increased by <code>7</code>.</li>
+<li><em>Poison</em> costs <code>173</code> mana.  It starts an <em>effect</em> that lasts for <code>6</code> turns.  At the start of each turn while it is active, it deals the boss <code>3</code> damage.</li>
+<li><em>Recharge</em> costs <code>229</code> mana.  It starts an <em>effect</em> that lasts for <code>5</code> turns.  At the start of each turn while it is active, it gives you <code>101</code> new mana.</li>
+</ul>
+<p><em>Effects</em> all work the same way.  Effects apply at the start of both the player's turns and the boss' turns.  Effects are created with a timer (the number of turns they last); at the start of each turn, after they apply any effect they have, their timer is decreased by one.  If this decreases the timer to zero, the effect ends.  You cannot cast a spell that would start an effect which is already active.  However, effects can be started on the same turn they end.</p>
+<p>For example, suppose the player has <code>10</code> hit points and <code>250</code> mana, and that the boss has <code>13</code> hit points and <code>8</code> damage:</p>
+<pre><code>-- Player turn --
+- Player has 10 hit points, 0 armor, 250 mana
+- Boss has 13 hit points
+Player casts Poison.
+
+-- Boss turn --
+- Player has 10 hit points, 0 armor, 77 mana
+- Boss has 13 hit points
+Poison deals 3 damage; its timer is now 5.
+Boss attacks for 8 damage.
+
+-- Player turn --
+- Player has 2 hit points, 0 armor, 77 mana
+- Boss has 10 hit points
+Poison deals 3 damage; its timer is now 4.
+Player casts Magic Missile, dealing 4 damage.
+
+-- Boss turn --
+- Player has 2 hit points, 0 armor, 24 mana
+- Boss has 3 hit points
+Poison deals 3 damage. This kills the boss, and the player wins.
+</code></pre>
+<p>Now, suppose the same initial conditions, except that the boss has <code>14</code> hit points instead:</p>
+<pre><code>-- Player turn --
+- Player has 10 hit points, 0 armor, 250 mana
+- Boss has 14 hit points
+Player casts Recharge.
+
+-- Boss turn --
+- Player has 10 hit points, 0 armor, 21 mana
+- Boss has 14 hit points
+Recharge provides 101 mana; its timer is now 4.
+Boss attacks for 8 damage!
+
+-- Player turn --
+- Player has 2 hit points, 0 armor, 122 mana
+- Boss has 14 hit points
+Recharge provides 101 mana; its timer is now 3.
+Player casts Shield, increasing armor by 7.
+
+-- Boss turn --
+- Player has 2 hit points, 7 armor, 110 mana
+- Boss has 14 hit points
+Shield's timer is now 5.
+Recharge provides 101 mana; its timer is now 2.
+Boss attacks for 8 - 7 = 1 damage!
+
+-- Player turn --
+- Player has 1 hit point, 7 armor, 211 mana
+- Boss has 14 hit points
+Shield's timer is now 4.
+Recharge provides 101 mana; its timer is now 1.
+Player casts Drain, dealing 2 damage, and healing 2 hit points.
+
+-- Boss turn --
+- Player has 3 hit points, 7 armor, 239 mana
+- Boss has 12 hit points
+Shield's timer is now 3.
+Recharge provides 101 mana; its timer is now 0.
+Recharge wears off.
+Boss attacks for 8 - 7 = 1 damage!
+
+-- Player turn --
+- Player has 2 hit points, 7 armor, 340 mana
+- Boss has 12 hit points
+Shield's timer is now 2.
+Player casts Poison.
+
+-- Boss turn --
+- Player has 2 hit points, 7 armor, 167 mana
+- Boss has 12 hit points
+Shield's timer is now 1.
+Poison deals 3 damage; its timer is now 5.
+Boss attacks for 8 - 7 = 1 damage!
+
+-- Player turn --
+- Player has 1 hit point, 7 armor, 167 mana
+- Boss has 9 hit points
+Shield's timer is now 0.
+Shield wears off, decreasing armor by 7.
+Poison deals 3 damage; its timer is now 4.
+Player casts Magic Missile, dealing 4 damage.
+
+-- Boss turn --
+- Player has 1 hit point, 0 armor, 114 mana
+- Boss has 2 hit points
+Poison deals 3 damage. This kills the boss, and the player wins.
+</code></pre>
+<p>You start with <em>50 hit points</em> and <em>500 mana points</em>. The boss's actual stats are in your puzzle input. What is the <em>least amount of mana</em> you can spend and still win the fight?  (Do not include mana recharge effects as "spending" negative mana.)</p>
+</article>
+<p>Your puzzle answer was <code>1269</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p>On the next run through the game, you increase the difficulty to <em>hard</em>.</p>
+<p>At the start of each <em>player turn</em> (before any other effects apply), you lose <code>1</code> hit point. If this brings you to or below <code>0</code> hit points, you lose.</p>
+<p>With the same starting stats for you and the boss, what is the <em>least amount of mana</em> you can spend and still win the fight?</p>
+</article>
+<p>Your puzzle answer was <code>1309</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p>
+<p>At this point, you should <a href="/">return to your advent calendar</a> and try another puzzle.</p>
+<p>If you still want to see it, you can <a href="/day/22/input" target="_blank">get your puzzle input</a>.</p>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Wizard+Simulator+20XX%22+%2D+Day+22+%2D+Advent+of+Code&amp;url=http%3A%2F%2Fadventofcode%2Ecom%2Fday%2F22&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="https://plus.google.com/share?url=http%3A%2F%2Fadventofcode%2Ecom%2Fday%2F22" target="_blank">Google+</a>
+  <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2Fday%2F22&amp;title=I%27ve+completed+%22Wizard+Simulator+20XX%22+%2D+Day+22+%2D+Advent+of+Code" target="_blank">Reddit</a
+></span>]</span>
+ this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
diff --git a/advent22.ipynb b/advent22.ipynb
new file mode 100644 (file)
index 0000000..f08ab26
--- /dev/null
@@ -0,0 +1,848 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "import copy"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
+       " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2},\n",
+       " {'cost': 113,\n",
+       "  'name': 'Shield',\n",
+       "  'ongoing': [{'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7}]},\n",
+       " {'cost': 173,\n",
+       "  'name': 'Poison',\n",
+       "  'ongoing': [{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]},\n",
+       " {'cost': 229,\n",
+       "  'name': 'Recharge',\n",
+       "  'ongoing': [{'mana': 101},\n",
+       "   {'mana': 101},\n",
+       "   {'mana': 101},\n",
+       "   {'mana': 101},\n",
+       "   {'mana': 101}]}]"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "spells = [\n",
+    "    {'name': 'Magic missile', 'cost': 53, 'boss_hp': -4},\n",
+    "    {'name': 'Drain', 'cost': 73, 'boss_hp': -2, 'pc_hp': 2},\n",
+    "    {'name': 'Shield', 'cost': 113, 'ongoing': [{'armour': 7}] * 6},\n",
+    "    {'name': 'Poison', 'cost': 173, 'ongoing': [{'boss_hp': -3}] * 6},\n",
+    "    {'name': 'Recharge', 'cost': 229, 'ongoing': [{'mana': 101}] * 5}]\n",
+    "spells"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 153,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [],
+   "source": [
+    "initial_state = {'pc_hp': 50, 'mana': 500, 'boss_hp': 58, 'boss_damage': 9, 'ongoing': [], \n",
+    "                 'spent': 0, 'cast': []}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 154,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def cast_spell(spell, state):\n",
+    "    new_state = copy.deepcopy(state)\n",
+    "    new_state['mana'] -= spell['cost']\n",
+    "    new_state['spent'] += spell['cost']\n",
+    "    new_state['cast'] += [spell['name']]\n",
+    "    if 'boss_hp' in spell:\n",
+    "        new_state['boss_hp'] += spell['boss_hp']\n",
+    "    if 'pc_hp' in spell:\n",
+    "        new_state['pc_hp'] += spell['pc_hp']\n",
+    "    if 'ongoing' in spell:\n",
+    "        new_state['ongoing'] += [spell['ongoing']]\n",
+    "    return new_state"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 155,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'boss_damage': 9,\n",
+       " 'boss_hp': 54,\n",
+       " 'cast': ['Magic missile'],\n",
+       " 'mana': 447,\n",
+       " 'ongoing': [],\n",
+       " 'pc_hp': 50,\n",
+       " 'spent': 53}"
+      ]
+     },
+     "execution_count": 155,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cast_spell(spells[0], initial_state)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 156,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'boss_damage': 9,\n",
+       " 'boss_hp': 58,\n",
+       " 'cast': [],\n",
+       " 'mana': 500,\n",
+       " 'ongoing': [],\n",
+       " 'pc_hp': 50,\n",
+       " 'spent': 0}"
+      ]
+     },
+     "execution_count": 156,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "initial_state"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 157,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'boss_damage': 9,\n",
+       " 'boss_hp': 58,\n",
+       " 'cast': ['Shield', 'Poison'],\n",
+       " 'mana': 214,\n",
+       " 'ongoing': [[{'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7}],\n",
+       "  [{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]],\n",
+       " 'pc_hp': 50,\n",
+       " 'spent': 286}"
+      ]
+     },
+     "execution_count": 157,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s2 = cast_spell(spells[2], initial_state)\n",
+    "cast_spell(spells[3], s2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 97,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def valid_spells(spells, state):\n",
+    "    valid_spells = []\n",
+    "    for spell in spells:\n",
+    "        add_this_spell = True\n",
+    "        if spell['cost'] > state['mana']:\n",
+    "            add_this_spell = False\n",
+    "        if 'ongoing' in spell:\n",
+    "            for s in spell['ongoing'][0]:\n",
+    "                for status in state['ongoing']:\n",
+    "                    if s in status[0]:\n",
+    "                        add_this_spell = False\n",
+    "        if add_this_spell:\n",
+    "            valid_spells += [spell]\n",
+    "    return valid_spells"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 98,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
+       " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2},\n",
+       " {'cost': 113,\n",
+       "  'name': 'Shield',\n",
+       "  'ongoing': [{'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7}]},\n",
+       " {'cost': 173,\n",
+       "  'name': 'Poison',\n",
+       "  'ongoing': [{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]},\n",
+       " {'cost': 229,\n",
+       "  'name': 'Recharge',\n",
+       "  'ongoing': [{'mana': 101},\n",
+       "   {'mana': 101},\n",
+       "   {'mana': 101},\n",
+       "   {'mana': 101},\n",
+       "   {'mana': 101}]}]"
+      ]
+     },
+     "execution_count": 98,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "valid_spells(spells, initial_state)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 158,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'boss_damage': 9,\n",
+       " 'boss_hp': 58,\n",
+       " 'cast': ['Shield', 'Poison'],\n",
+       " 'mana': 214,\n",
+       " 'ongoing': [[{'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7}],\n",
+       "  [{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]],\n",
+       " 'pc_hp': 50,\n",
+       " 'spent': 286}"
+      ]
+     },
+     "execution_count": 158,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s2 = cast_spell(spells[2], initial_state)\n",
+    "s3 = cast_spell(spells[3], s2)\n",
+    "s3"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 159,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
+       " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2}]"
+      ]
+     },
+     "execution_count": 159,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "valid_spells(spells, s3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def boss_turn(state):\n",
+    "    new_state = apply_ongoing(state)\n",
+    "    if new_state['boss_hp'] > 0:\n",
+    "        new_state['pc_hp'] -= max(new_state['boss_damage'] - new_state['armour'], 1)\n",
+    "    return new_state"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 67,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def apply_ongoing(state):\n",
+    "    new_state = copy.deepcopy(state)\n",
+    "    new_state['armour'] = 0\n",
+    "    new_state['ongoing'] = []\n",
+    "    for status in state['ongoing']:\n",
+    "        for k in status[0]:\n",
+    "            new_state[k] += status[0][k]\n",
+    "        if len(status) > 1:\n",
+    "            new_state['ongoing'] += [status[1:]]\n",
+    "    return new_state"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 160,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 7,\n",
+       " 'boss_damage': 9,\n",
+       " 'boss_hp': 55,\n",
+       " 'cast': ['Shield', 'Poison'],\n",
+       " 'mana': 214,\n",
+       " 'ongoing': [[{'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7},\n",
+       "   {'armour': 7}],\n",
+       "  [{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]],\n",
+       " 'pc_hp': 48,\n",
+       " 'spent': 286}"
+      ]
+     },
+     "execution_count": 160,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "boss_turn(s3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 161,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 0,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': 10,\n",
+       " 'cast': ['Poison'],\n",
+       " 'mana': 77,\n",
+       " 'ongoing': [[{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]],\n",
+       " 'pc_hp': 2,\n",
+       " 'spent': 173}"
+      ]
+     },
+     "execution_count": 161,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "test_state_1 = {'pc_hp': 10, 'mana': 250, 'boss_hp': 13, 'boss_damage': 8, 'ongoing': [], 'spent': 0, 'cast': []}\n",
+    "s2 = cast_spell([s for s in spells if s['name'] == 'Poison'][0], test_state_1)\n",
+    "s3 = boss_turn(s2)\n",
+    "s3"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 162,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 0,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': 0,\n",
+       " 'cast': ['Poison', 'Magic missile'],\n",
+       " 'mana': 24,\n",
+       " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}, {'boss_hp': -3}]],\n",
+       " 'pc_hp': 2,\n",
+       " 'spent': 226}"
+      ]
+     },
+     "execution_count": 162,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s4 = apply_ongoing(s3)\n",
+    "s5 = cast_spell([s for s in spells if s['name'] == 'Magic missile'][0], s4)\n",
+    "s6 = boss_turn(s5)\n",
+    "s6"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 163,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 0,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': 14,\n",
+       " 'cast': ['Recharge'],\n",
+       " 'mana': 122,\n",
+       " 'ongoing': [[{'mana': 101}, {'mana': 101}, {'mana': 101}, {'mana': 101}]],\n",
+       " 'pc_hp': 2,\n",
+       " 'spent': 229}"
+      ]
+     },
+     "execution_count": 163,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "test_state_2 = {'pc_hp': 10, 'mana': 250, 'boss_hp': 14, 'boss_damage': 8, 'ongoing': [], 'spent': 0, 'cast': []}\n",
+    "s2 = cast_spell([s for s in spells if s['name'] == 'Recharge'][0], test_state_2)\n",
+    "s3 = boss_turn(s2)\n",
+    "s3"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 164,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 7,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': 14,\n",
+       " 'cast': ['Recharge', 'Shield'],\n",
+       " 'mana': 211,\n",
+       " 'ongoing': [[{'mana': 101}, {'mana': 101}],\n",
+       "  [{'armour': 7}, {'armour': 7}, {'armour': 7}, {'armour': 7}, {'armour': 7}]],\n",
+       " 'pc_hp': 1,\n",
+       " 'spent': 342}"
+      ]
+     },
+     "execution_count": 164,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s4 = apply_ongoing(s3)\n",
+    "s5 = cast_spell([s for s in spells if s['name'] == 'Shield'][0], s4)\n",
+    "s6 = boss_turn(s5)\n",
+    "s6"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 165,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 7,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': 12,\n",
+       " 'cast': ['Recharge', 'Shield', 'Drain'],\n",
+       " 'mana': 340,\n",
+       " 'ongoing': [[{'armour': 7}, {'armour': 7}, {'armour': 7}]],\n",
+       " 'pc_hp': 2,\n",
+       " 'spent': 415}"
+      ]
+     },
+     "execution_count": 165,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s7 = apply_ongoing(s6)\n",
+    "s8 = cast_spell([s for s in spells if s['name'] == 'Drain'][0], s7)\n",
+    "s9 = boss_turn(s8)\n",
+    "s9"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 166,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 7,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': 9,\n",
+       " 'cast': ['Recharge', 'Shield', 'Drain', 'Poison'],\n",
+       " 'mana': 167,\n",
+       " 'ongoing': [[{'armour': 7}],\n",
+       "  [{'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3},\n",
+       "   {'boss_hp': -3}]],\n",
+       " 'pc_hp': 1,\n",
+       " 'spent': 588}"
+      ]
+     },
+     "execution_count": 166,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s10 = apply_ongoing(s9)\n",
+    "s11 = cast_spell([s for s in spells if s['name'] == 'Poison'][0], s10)\n",
+    "s12 = boss_turn(s11)\n",
+    "s12"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 167,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 0,\n",
+       " 'boss_damage': 8,\n",
+       " 'boss_hp': -1,\n",
+       " 'cast': ['Recharge', 'Shield', 'Drain', 'Poison', 'Magic missile'],\n",
+       " 'mana': 114,\n",
+       " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}, {'boss_hp': -3}]],\n",
+       " 'pc_hp': 1,\n",
+       " 'spent': 641}"
+      ]
+     },
+     "execution_count": 167,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "s13 = apply_ongoing(s12)\n",
+    "s14 = cast_spell([s for s in spells if s['name'] == 'Magic missile'][0], s13)\n",
+    "s15 = boss_turn(s14)\n",
+    "s15"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 90,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def finished(state):\n",
+    "    return state['boss_hp'] <= 0 or state['pc_hp'] <= 0\n",
+    "\n",
+    "def victory(state):\n",
+    "    return finished(state) and state['pc_hp'] > 0\n",
+    "\n",
+    "def defeat(state):\n",
+    "    return finished(state) and state['pc_hp'] <= 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 125,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [],
+   "source": [
+    "def ahistoric(state):\n",
+    "    return {k: state[k] for k in state if k != 'cast'}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 186,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 7,\n",
+       " 'boss_damage': 9,\n",
+       " 'boss_hp': 0,\n",
+       " 'cast': ['Poison',\n",
+       "  'Recharge',\n",
+       "  'Drain',\n",
+       "  'Poison',\n",
+       "  'Recharge',\n",
+       "  'Shield',\n",
+       "  'Poison',\n",
+       "  'Magic missile',\n",
+       "  'Magic missile'],\n",
+       " 'mana': 241,\n",
+       " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}]],\n",
+       " 'pc_hp': 1,\n",
+       " 'spent': 1269}"
+      ]
+     },
+     "execution_count": 186,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "agenda = [initial_state]\n",
+    "closed = []\n",
+    "while agenda:\n",
+    "        current_state = agenda[0]\n",
+    "        new_states = []\n",
+    "        if ahistoric(current_state) not in closed:\n",
+    "            closed += [ahistoric(current_state)]\n",
+    "            # print(current_state)\n",
+    "            if victory(current_state):\n",
+    "                # return current_state\n",
+    "                break\n",
+    "            for spell in valid_spells(spells, current_state):\n",
+    "                s2 = cast_spell(spell, current_state)\n",
+    "                if victory(s2):\n",
+    "                    new_states += [s2]\n",
+    "                else:\n",
+    "                    s3 = boss_turn(s2)\n",
+    "                    if victory(s3):\n",
+    "                        new_states += [s3]\n",
+    "                    if not finished(s3):\n",
+    "                        new_states += [apply_ongoing(s3)]\n",
+    "        # print(new_states)\n",
+    "        states_to_add = [s for s in new_states \n",
+    "                         if ahistoric(s) not in closed\n",
+    "                         if len(s['cast']) <= 50]\n",
+    "        agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
+    "        # agenda = new_states + agenda[1:]\n",
+    "current_state"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#Part 2"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 182,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def player_bleed(state):\n",
+    "    new_state = copy.deepcopy(state)\n",
+    "    new_state['pc_hp'] -= 1\n",
+    "    return new_state"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 185,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'armour': 0,\n",
+       " 'boss_damage': 9,\n",
+       " 'boss_hp': -1,\n",
+       " 'cast': ['Poison',\n",
+       "  'Recharge',\n",
+       "  'Shield',\n",
+       "  'Poison',\n",
+       "  'Recharge',\n",
+       "  'Shield',\n",
+       "  'Poison',\n",
+       "  'Magic missile',\n",
+       "  'Magic missile'],\n",
+       " 'mana': 201,\n",
+       " 'ongoing': [[{'boss_hp': -3}]],\n",
+       " 'pc_hp': 12,\n",
+       " 'spent': 1309}"
+      ]
+     },
+     "execution_count": 185,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "agenda = [initial_state]\n",
+    "closed = []\n",
+    "while agenda:\n",
+    "        current_state = agenda[0]\n",
+    "        new_states = []\n",
+    "        if ahistoric(current_state) not in closed:\n",
+    "            closed += [ahistoric(current_state)]\n",
+    "            # print(current_state)\n",
+    "            if victory(current_state):\n",
+    "                # return current_state\n",
+    "                break\n",
+    "            for spell in valid_spells(spells, current_state):\n",
+    "                s2 = cast_spell(spell, current_state)\n",
+    "                if victory(s2):\n",
+    "                    new_states += [s2]\n",
+    "                else:\n",
+    "                    s3 = boss_turn(s2)\n",
+    "                    if victory(s3):\n",
+    "                        new_states += [s3]\n",
+    "                    s4 = player_bleed(s3)\n",
+    "                    if not finished(s4):\n",
+    "                        new_states += [apply_ongoing(s4)]\n",
+    "        # print(new_states)\n",
+    "        states_to_add = [s for s in new_states \n",
+    "                         if ahistoric(s) not in closed\n",
+    "                         if len(s['cast']) <= 50]\n",
+    "        agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
+    "        # agenda = new_states + agenda[1:]\n",
+    "current_state"
+   ]
+  },
+  {
+   "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
+}