diff --git a/ipynb/Advent 2017.ipynb b/ipynb/Advent 2017.ipynb index 1197420..3087c8e 100644 --- a/ipynb/Advent 2017.ipynb +++ b/ipynb/Advent 2017.ipynb @@ -411,7 +411,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This was an easy warmup puzzle. I forgot that Advent of Code was starting at 9:00PM my time, so I started late, but even if I had started on time, I doubt I would have been fast enough to score points. (I created a recurring calendar reminder so I'll be more likely to start on time in the future.)" + "This was an easy warmup puzzle. " ] }, { @@ -501,9 +501,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This day was also very easy. In Part One, I was slowed down by a typo: I had `\"=\"` instead of `\"-\"` in `\"max(row) - min(row)\"`. I was confused by Python's misleading error message, which said `\"SyntaxError: keyword can't be an expression\"`. Later on, Alex Martelli explained to me that the message meant that in `abs(max(row)=...)` it thought that `max(row)` was a keyword argument to `abs`. \n", + "This day was also very easy. In Part One, I was slowed down by a typo: I had `\"=\"` instead of `\"-\"` in `\"max(row) - min(row)\"`. I was confused by Python's misleading error message, which said `\"SyntaxError: keyword can't be an expression\"`. Later on, Alex Martelli explained to me that the message meant that in `abs(max(row)=...)` it thought that `max(row)` was a keyword argument to `abs`, as in `abs(x=-1)`.\n", "\n", - "In Part Two, note that to check that `a/b` is an exact integer, I used `a // b == a / b`, which I think is more clear and less error-prone than the expression one would typically use here, `a % b == 0`." + "In Part Two, note that to check that `a/b` is an exact integer, I used `a // b == a / b`, which I think is more clear and less error-prone than the expression one would typically use here, `a % b == 0`, which requires you to think about two things: division and the modulus operator (is it `a % b` or `b % a`?)." ] }, { @@ -653,7 +653,7 @@ "outputs": [], "source": [ "def spiralsums():\n", - " \"Yield the values of a spiral where each point has the sum of the 8 neighbors.\"\n", + " \"Yield the values of a spiral where each square has the sum of the 8 neighbors.\"\n", " value = defaultdict(int)\n", " for p in spiral():\n", " value[p] = sum(value[q] for q in neighbors8(p)) or 1\n", @@ -775,7 +775,158 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "It took me less than five minutes, and my preparation with `Input` and `canon` helped, but I was still too slow to score any points." + "It took me less than five minutes, and my preparation with `Input` and `canon` helped, but I was still too slow to score any points--the top 20 took less than two minutes each." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Day 5](https://adventofcode.com/2017/day/5): A Maze of Twisty Trampolines, All Alike\n", + "\n", + "Let's first make sure we can read the data okay:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 2, 0, 0, -2, -2, -1, -4, -5, -6]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def jumps(): return [int(x) for x in Input(5)]\n", + "\n", + "jumps()[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now I'll make a little interpreter, `run`, which takes a list, `M` for memory, as input,\n", + "and maintains a program counter `pc`, and does the incrementing as described in the puzzle,\n", + "until the program counter is out of range:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "364539" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def run(M):\n", + " pc = 0\n", + " for steps in count_from(1):\n", + " oldpc = pc\n", + " pc += M[pc]\n", + " M[oldpc] += 1\n", + " if pc not in range(len(M)):\n", + " return steps\n", + " \n", + "run(jumps())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Part Two:**\n", + "\n", + "Part Two seems tricky, so I'll include an optional argument, `verbose`, to print out info as we go, to make sure I've got it right on a small example:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 0 [1, 3, 0, 1, -3]\n", + "2 1 [2, 3, 0, 1, -3]\n", + "3 4 [2, 2, 0, 1, -3]\n", + "4 1 [2, 2, 0, 1, -2]\n", + "5 3 [2, 3, 0, 1, -2]\n", + "6 4 [2, 3, 0, 2, -2]\n", + "7 2 [2, 3, 0, 2, -1]\n", + "8 2 [2, 3, 1, 2, -1]\n", + "9 3 [2, 3, 2, 2, -1]\n", + "10 5 [2, 3, 2, 3, -1]\n" + ] + }, + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def run2(M, verbose=False):\n", + " pc = 0\n", + " for steps in count_from(1):\n", + " oldpc = pc\n", + " pc += M[pc]\n", + " M[oldpc] += (-1 if M[oldpc] >= 3 else 1)\n", + " if verbose: print(steps, pc, M)\n", + " if pc not in range(len(M)):\n", + " return steps\n", + " \n", + "run2([0, 3, 0, 1, -3], True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That looks right, so I can solve the puzzle:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "27477714" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "run2(jumps())" ] } ],