From 8a82f9afe493c9cff8c167a6aeb0ed38b24d2f0c Mon Sep 17 00:00:00 2001 From: Peter Norvig Date: Wed, 20 Dec 2017 00:33:59 -0800 Subject: [PATCH] Advent 2017 through Day 20 --- ipynb/Advent 2017.ipynb | 446 ++++++++++++++++++++++++++-------------- 1 file changed, 292 insertions(+), 154 deletions(-) diff --git a/ipynb/Advent 2017.ipynb b/ipynb/Advent 2017.ipynb index c2db159..b67c5b6 100644 --- a/ipynb/Advent 2017.ipynb +++ b/ipynb/Advent 2017.ipynb @@ -49,6 +49,7 @@ "from itertools import (permutations, combinations, chain, cycle, product, islice, \n", " takewhile, zip_longest, count as count_from)\n", "from heapq import heappop, heappush\n", + "from numba import jit\n", "\n", "identity = lambda x: x\n", "letters = 'abcdefghijklmnopqrstuvwxyz'\n", @@ -66,21 +67,25 @@ "def Input(day, year=2017):\n", " \"Open this day's input file.\"\n", " return open('data/advent{}/input{}.txt'.format(year, day))\n", + "\n", + "def Inputstr(day, year=2017): \n", + " \"The contents of this day's input file as a str.\"\n", + " return Input(day, year).read().rstrip('\\n')\n", " \n", - "def array(lines):\n", + "def Array(lines):\n", " \"Parse an iterable of str lines into a 2-D array. If `lines` is a str, splitlines.\"\n", " if isinstance(lines, str): lines = lines.splitlines()\n", - " return mapt(vector, lines)\n", + " return mapt(Vector, lines)\n", "\n", - "def vector(line):\n", + "def Vector(line):\n", " \"Parse a str into a tuple of atoms (numbers or str tokens).\"\n", - " return mapt(atom, line.replace(',', ' ').split())\n", + " return mapt(Atom, line.replace(',', ' ').split())\n", "\n", - "def integers(text): \n", + "def Integers(text): \n", " \"Return a tuple of all integers in a string.\"\n", - " return mapt(int, re.findall(r'\\b[-+]?\\d+\\b', text))\n", + " return mapt(int, re.findall(r'-?\\b\\d+\\b', text))\n", "\n", - "def atom(token):\n", + "def Atom(token):\n", " \"Parse a str token into a number, or leave it as a str.\"\n", " try:\n", " return int(token)\n", @@ -160,6 +165,10 @@ " \"Count how many times the predicate is true.\"\n", " return sum(map(pred, iterable))\n", "\n", + "def length(iterable):\n", + " \"Same as len(list(iterable)), but without consuming memory.\"\n", + " return sum(1 for _ in iterable)\n", + "\n", "def shuffled(iterable):\n", " \"Create a new list out of iterable, and shuffle it.\"\n", " new = list(iterable)\n", @@ -194,7 +203,7 @@ " return range(start, end + 1)\n", "\n", "def floats(start, end, step=1.0):\n", - " \"Yields from start to end (inclusive), by increments of step.\"\n", + " \"Yield floats from start to end (inclusive), by increments of step.\"\n", " m = (1.0 if step >= 0 else -1.0)\n", " while start * m <= end * m:\n", " yield start\n", @@ -236,13 +245,13 @@ " (x-1, y), (x+1, y),\n", " (x-1, y+1), (x, y+1), (x+1, y+1))\n", "\n", - "def cityblock_distance(p, q=origin): \n", + "def cityblock_distance(P, Q=origin): \n", " \"Manhatten distance between two points.\"\n", - " return abs(X(p) - X(q)) + abs(Y(p) - Y(q))\n", + " return sum(abs(p - q) for p, q in zip(P, Q))\n", "\n", - "def distance(p, q=origin): \n", + "def distance(P, Q=origin): \n", " \"Hypotenuse distance between two points.\"\n", - " return math.hypot(X(p) - X(q), Y(p) - Y(q))\n", + " return sum((p - q) ** 2 for p, q in zip(P, Q)) ** 0.5\n", "\n", "################ Debugging \n", "\n", @@ -263,6 +272,10 @@ "class Struct:\n", " \"A structure that can have any fields defined.\"\n", " def __init__(self, **entries): self.__dict__.update(entries)\n", + " def __repr__(self): \n", + " fields = ['{}={}'.format(f, self.__dict__[f]) \n", + " for f in sorted(self.__dict__)]\n", + " return 'Struct({})'.format(', '.join(fields))\n", "\n", "################ A* and Breadth-First Search (tracking states, not actions)\n", "\n", @@ -310,10 +323,10 @@ "source": [ "def tests():\n", " # Functions for Input, Parsing\n", - " assert array('''1 2 3\n", + " assert Array('''1 2 3\n", " 4 5 6''') == ((1, 2, 3), \n", " (4, 5, 6))\n", - " assert vector('testing 1 2 3.') == ('testing', 1, 2, 3.0)\n", + " assert Vector('testing 1 2 3.') == ('testing', 1, 2, 3.0)\n", " \n", " # Functions on Iterables\n", " assert first('abc') == first(['a', 'b', 'c']) == 'a'\n", @@ -385,7 +398,7 @@ { "data": { "text/plain": [ - "2014" + "(2014, (3, 2, 9, 4, 1, 9, 9, 4, 7, 1))" ] }, "execution_count": 3, @@ -394,9 +407,10 @@ } ], "source": [ - "digits = mapt(int, '3294199471327195994824832197564859876682638188889768298894243832665654681412886862234525991553276578641265589959178414218389329361496673991614673626344552179413995562266818138372393213966143124914469397692587251112663217862879233226763533911128893354536353213847122251463857894159819828724827969576432191847787772732881266875469721189331882228146576832921314638221317393256471998598117289632684663355273845983933845721713497811766995367795857965222183668765517454263354111134841334631345111596131682726196574763165187889337599583345634413436165539744188866156771585647718555182529936669683581662398618765391487164715724849894563314426959348119286955144439452731762666568741612153254469131724137699832984728937865956711925592628456617133695259554548719328229938621332325125972547181236812263887375866231118312954369432937359357266467383318326239572877314765121844831126178173988799765218913178825966268816476559792947359956859989228917136267178571776316345292573489873792149646548747995389669692188457724414468727192819919448275922166321158141365237545222633688372891451842434458527698774342111482498999383831492577615154591278719656798277377363284379468757998373193231795767644654155432692988651312845433511879457921638934877557575241394363721667237778962455961493559848522582413748218971212486373232795878362964873855994697149692824917183375545192119453587398199912564474614219929345185468661129966379693813498542474732198176496694746111576925715493967296487258237854152382365579876894391815759815373319159213475555251488754279888245492373595471189191353244684697662848376529881512529221627313527441221459672786923145165989611223372241149929436247374818467481641931872972582295425936998535194423916544367799522276914445231582272368388831834437562752119325286474352863554693373718848649568451797751926315617575295381964426843625282819524747119726872193569785611959896776143539915299968276374712996485367853494734376257511273443736433464496287219615697341973131715166768916149828396454638596713572963686159214116763')\n", + "digits = mapt(int, Inputstr(1))\n", "N = len(digits)\n", - "N" + "\n", + "N, digits[:10]" ] }, { @@ -465,7 +479,7 @@ }, "outputs": [], "source": [ - "rows2 = array('''790\t99\t345\t1080\t32\t143\t1085\t984\t553\t98\t123\t97\t197\t886\t125\t947\n", + "rows2 = Array('''790\t99\t345\t1080\t32\t143\t1085\t984\t553\t98\t123\t97\t197\t886\t125\t947\n", "302\t463\t59\t58\t55\t87\t508\t54\t472\t63\t469\t419\t424\t331\t337\t72\n", "899\t962\t77\t1127\t62\t530\t78\t880\t129\t1014\t93\t148\t239\t288\t357\t424\n", "2417\t2755\t254\t3886\t5336\t3655\t5798\t3273\t5016\t178\t270\t6511\t223\t5391\t1342\t2377\n", @@ -946,8 +960,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 6.21 s, sys: 24.6 ms, total: 6.24 s\n", - "Wall time: 6.28 s\n" + "CPU times: user 6.15 s, sys: 19.9 ms, total: 6.17 s\n", + "Wall time: 6.19 s\n" ] }, { @@ -994,7 +1008,7 @@ }, "outputs": [], "source": [ - "banks = vector('4\t10\t4\t1\t8\t4\t9\t14\t5\t1\t14\t15\t0\t15\t3\t5')\n", + "banks = Vector('4\t10\t4\t1\t8\t4\t9\t14\t5\t1\t14\t15\t0\t15\t3\t5')\n", "\n", "def realloc(banks):\n", " \"How many cycles until we reach a configuration we've seen before?\"\n", @@ -1349,7 +1363,7 @@ "source": [ "# [Day 8](https://adventofcode.com/2017/day/8): Memory Reallocation \n", "\n", - "This one looks easy: a simple interpreter for straight-line code where each instruction has 7 tokens. It is nice that my `array` function parses the whole program." + "This one looks easy: a simple interpreter for straight-line code where each instruction has 7 tokens. It is nice that my `Array` function parses the whole program." ] }, { @@ -1369,7 +1383,7 @@ } ], "source": [ - "program8 = array(Input(8))\n", + "program8 = Array(Input(8))\n", "\n", "def run8(program):\n", " \"Run the program and return final value of registers.\"\n", @@ -1446,8 +1460,8 @@ } ], "source": [ - "text1 = re.sub(r'!.', '', Input(9).read()) # Delete canceled characters\n", - "text2 = re.sub(r'<.*?>', '', text1) # Delete garbage\n", + "text1 = re.sub(r'!.', '', Inputstr(9)) # Delete canceled characters\n", + "text2 = re.sub(r'<.*?>', '', text1) # Delete garbage\n", "\n", "text2[:70]" ] @@ -1781,7 +1795,7 @@ } ], "source": [ - "path = vector(Input(11).read())\n", + "path = Vector(Inputstr(11))\n", "\n", "def follow(path):\n", " \"Follow each step of the path; return final distance to origin.\"\n", @@ -1854,7 +1868,7 @@ "def groups(lines):\n", " \"Dict of {i: {directly_connected_to_i}\"\n", " return {lhs: {lhs} | set(rhs)\n", - " for (lhs, _, *rhs) in array(lines)}\n", + " for (lhs, _, *rhs) in Array(lines)}\n", " \n", "assert groups(Input(12))[0] == {0, 659, 737}" ] @@ -1988,7 +2002,7 @@ } ], "source": [ - "scanners = mapt(integers, Input(13))\n", + "scanners = mapt(Integers, Input(13))\n", "scanners[:5]" ] }, @@ -2127,16 +2141,18 @@ { "cell_type": "code", "execution_count": 61, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "def Grid(key, N=128+2):\n", " \"Make a grid, with a border around it.\"\n", - " rows = [['0'] + list(bits(key, i)) + ['0'] \n", - " for i in range(128)]\n", - " empty = ['0'] * len(rows[0])\n", + " return border('0', (list(bits(key, i)) for i in range(128)))\n", + "\n", + "def border(fill, grid):\n", + " \"Surround a grid with a border of fill cells.\"\n", + " rows = [[fill] + list(row) + [fill] \n", + " for row in grid]\n", + " empty = [fill] * len(rows[0])\n", " return [empty] + rows + [empty]" ] }, @@ -2220,8 +2236,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 24.8 s, sys: 64 ms, total: 24.9 s\n", - "Wall time: 24.9 s\n" + "CPU times: user 15.2 s, sys: 18.4 ms, total: 15.3 s\n", + "Wall time: 15.3 s\n" ] }, { @@ -2236,6 +2252,7 @@ } ], "source": [ + "@jit # This was the slowest solution; @jit helps a bit.\n", "def gen(prev, factor, m=2147483647):\n", " \"Generate a sequence of numbers according to the rules; stop at 0.\"\n", " while prev:\n", @@ -2243,7 +2260,7 @@ " yield prev\n", " \n", "def judge(A, B, N=40*10**6, mask=2**16-1): \n", - " \"How many of the first N pairs from A and B agree in the last b bits?\"\n", + " \"How many of the first N numbers from A and B agree in the masked bits (default last 16)?\"\n", " return quantify(a & mask == b & mask\n", " for (a, b, _) in zip(A, B, range(N)))\n", "\n", @@ -2257,6 +2274,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "Notice I also decided to use `@jit` (i.e. `numba.jit`) to speed things up, since this is the slowest-running day yet.\n", + "\n", "**Part Two**\n", "\n", "A small change: only consider numbers that match the **criteria** of being divisible by 4 or 8, respectively;" @@ -2271,8 +2290,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 16.3 s, sys: 23.3 ms, total: 16.4 s\n", - "Wall time: 16.4 s\n" + "CPU times: user 9.52 s, sys: 9 ms, total: 9.53 s\n", + "Wall time: 9.54 s\n" ] }, { @@ -2329,7 +2348,7 @@ } ], "source": [ - "dance = vector(Input(16).read())\n", + "dance = Vector(Inputstr(16))\n", "dance[:10]" ] }, @@ -2385,7 +2404,7 @@ " for move in dance:\n", " op, arg = move[0], move[1:]\n", " if op == 's': D.rotate(int(arg))\n", - " elif op == 'x': swap(*integers(arg))\n", + " elif op == 'x': swap(*Integers(arg))\n", " elif op == 'p': swap(D.index(arg[0]), D.index(arg[2]))\n", " return cat(D)\n", " \n", @@ -2539,7 +2558,7 @@ "\n", "**Part Two**\n", "\n", - "But Part Two is not so easy, if we care about the run time. Insertion into a `list` has to move all the elements after the insertion down, so insertion is O(N) and `spinlock` is O(N2). That's no problem when N = 2017, but a big problem when N is 50 million. We're gonna need need a bigger boat, where by \"boat\" I mean algorithm or data structure. My first thought is a (circular) linked list, because insertion is O(1). I can implement the three key methods: `skip` to move ahead, `insert` to add a new node after the current one, and `find` to find a piece of data (with a linear search):" + "But Part Two is not so easy, if we care about the run time. Insertion into a `list` has to move all the elements after the insertion down, so insertion is O(N) and `spinlock` is O(N2). That's no problem when N = 2017, but when N is 50 million? We're gonna need a bigger boat, where by \"boat\" I mean algorithm or data structure. My first thought is a (circular) linked list, because insertion is O(1). I can implement the three key methods: `skip` to move ahead, `insert` to add a new node after the current one, and `find` to find a piece of data (with a linear search):" ] }, { @@ -2641,14 +2660,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1.4 s, sys: 5.52 ms, total: 1.4 s\n", - "Wall time: 1.4 s\n" + "CPU times: user 1.57 s, sys: 7.74 ms, total: 1.58 s\n", + "Wall time: 1.58 s\n" ] }, { "data": { "text/plain": [ - "<__main__.Node at 0x108a9c780>" + "<__main__.Node at 0x111355438>" ] }, "execution_count": 77, @@ -2681,8 +2700,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 5.55 s, sys: 16.7 ms, total: 5.57 s\n", - "Wall time: 5.57 s\n" + "CPU times: user 5.48 s, sys: 8.31 ms, total: 5.49 s\n", + "Wall time: 5.49 s\n" ] }, { @@ -2714,7 +2733,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The moral of the story is *keep your eyes on the prize*. I got distracted because I asked the wrong question. I asked myself \"what's wrong with my solution in `spinlock`?\" and answered myself \"insertion is O(N2) and it should be O(N).\" I knew how to do that, but that was the wrong question. I should have asked myself \"how do I solve Part Two quickly,\" concentrating on solving the actual problem, and avoiding getting fixated on my solution to Part One." + "The moral of the story is *keep your eyes on the prize*. I got distracted because I asked the wrong question. I asked myself \"how can I make my solution in `spinlock` faster?\" and answered myself \"insertion is O(N2) and it should be O(N).\" I knew how to do that, with a linked list, but that was the right answer to the wrong question. I should have asked myself \"how do I solve Part Two quickly,\" concentrating on solving the actual problem. Once I did that, I realized I didn't need all those insertions: not doing them at all is a better idea than doing them faster." ] }, { @@ -2723,7 +2742,7 @@ "source": [ "# [Day 18](https://adventofcode.com/2017/day/17): Duet\n", "\n", - "First, read and take a peek at the input:" + "First, read the input, and take a peak at it:" ] }, { @@ -2738,7 +2757,12 @@ " ('set', 'a', 1),\n", " ('mul', 'p', 17),\n", " ('jgz', 'p', 'p'),\n", - " ('mul', 'a', 2))" + " ('mul', 'a', 2),\n", + " ('add', 'i', -1),\n", + " ('jgz', 'i', -2),\n", + " ('add', 'a', -1),\n", + " ('set', 'i', 127),\n", + " ('set', 'p', 826))" ] }, "execution_count": 79, @@ -2747,8 +2771,8 @@ } ], "source": [ - "program18 = array(Input(18))\n", - "program18[:5]" + "program18 = Array(Input(18))\n", + "program18[:10]" ] }, { @@ -2776,22 +2800,21 @@ ], "source": [ "def run18(program):\n", - " \"Interpret the assembly language program.\"\n", + " \"Interpret the assembly language program; return recovered `snd`.\"\n", " regs = defaultdict(int)\n", - " pc = sound = 0\n", + " pc = snd = 0\n", " while True:\n", " instr = program[pc]\n", + " pc += 1\n", " op, x, y = instr[0], instr[1], instr[-1]\n", " vy = value(regs, y)\n", - " if op == 'snd': sound = regs[x]\n", + " if op == 'snd': snd = regs[x]\n", " elif op == 'set': regs[x] = vy\n", " elif op == 'add': regs[x] += vy\n", " elif op == 'mul': regs[x] *= vy\n", " elif op == 'mod': regs[x] %= vy\n", " elif op == 'jgz' and regs[x] > 0: pc += vy - 1\n", - " elif op == 'rcv' and regs[x] != 0: \n", - " return sound\n", - " pc += 1\n", + " elif op == 'rcv' and regs[x] != 0: return snd\n", " \n", "def value(regs, y): return (y if isinstance(y, int) else regs[y])\n", "\n", @@ -2802,12 +2825,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "That was easy. (One tricky bit: after every instruction the `pc` is incremented by 1, so for the `'jgz'` jump instruction, the increment is `vy - 1`, not just `vy`, so that the `pc += 1` will fix it.)\n", + "That was easy. (One tricky bit: the `pc` is incremented by 1 every time through the loop, regardless of the instruction. Therefore, the `'jgz'` jump instruction increments by \"`vy - 1`\" so that the net increment is \"`vy`\".)\n", "\n", "**Part Two**\n", "\n", - "Now we have to run two copies of the program, and send messages between them. I'll break up the loop in `run18` into\n", - "two functions. First, `run18_2`, creates (in `ps`) two structures to hold the state variables necessary to run a program (`Struct` is my generic constructor of structures with named fields). `run18_2` then repeatedly calls `step18(program, p)` to execute one instruction of `program` with the state variables in `p`. At each step I will choose randomly which of the two programs to advance. (I could just as easily have alternated.) The function exits when neither copy of the program can run, according to their status. A program can have status `run` when it is ready to execute an instruction, `wait` when it is waiting for a value to arrive in its input queue, or `end` for when the `pc` has run off the end of the program and it is terminated." + "In Part Two we have to run two copies of the program, and send messages between them. I'll break up the loop in `run18` into\n", + "two functions. First, `run18_2`, creates (in `ps`) two structures to hold the state variables necessary to run a program:\n", + "- `id`: The id number (0 or 1) of this copy of the program.\n", + "- `pc`: The program counter.\n", + "- `sends`: A count of the number of `snd` instructions executed.\n", + "- `regs`: A dict of the program registers (`a` to `z`).\n", + "- `status`: A program has a status which can be:\n", + " * `'run'` when it is ready to execute an instruction, \n", + " * `'wait'` when it is waiting for a value to arrive in its input queue, or \n", + " * `'end'` when the `pc` has run off the end of the program and it has terminated.\n", + "\n", + "`run18_2` repeatedly calls the second function, `step18(program, p)` to execute one instruction of `program` with the state variables in `p`. I choose randomly which of the two programs to step on each iteration. The function exits when neither copy of the program can run, according to their status. " ] }, { @@ -2821,10 +2854,10 @@ "def run18_2(program):\n", " \"Run two copies of program, with different state variables. Return final states.\"\n", " Qs = [deque(), deque()]\n", - " ps = [Struct(pc=0, sends=0, Qs=Qs, status='run', p=id, regs=defaultdict(int, p=id))\n", + " ps = [Struct(id=id, pc=0, sends=0, regs=defaultdict(int, p=id), status='run')\n", " for id in (0, 1)]\n", - " while 'run' in {ps[0].status, ps[1].status}:\n", - " step18(program, random.choice(ps))\n", + " while any(p.status == 'run' for p in ps):\n", + " step18(program, Qs, random.choice(ps))\n", " return ps" ] }, @@ -2832,12 +2865,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The second function, `step18`, has most of the guts of `run18`, but with a few changes:\n", + "`step18` has most of the guts of thee previous `run18` function, but with a few changes:\n", "- State variables are accessed indirectly: `p.pc` instead of just `pc`.\n", "- If the `pc` is out of bounds, the program terminates; the status is set to `'end'`.\n", "- The `snd` instruction sends a value to the other program's queue.\n", - "- The `rcv` instruction pops a value of the queue if there is one, otherwise the status is set to `'wait'`.\n", - "- I was stuck for a *long* time on this problem, repeatedly getting the wrong answer. Finally I tried the strategy of *look carefully at the input*. I noticed an instruction, `\"jgz 1 3\"`, in which the X field was the integer 1. I had assumed the X field was always a register, but apparently it need not be, and I should be evaluating X with `value(regs, x)`, not `regs[x]`. Once I made that change, the program worked." + "- The `rcv` instruction pops a value off the queue if there is one, otherwise the status is set to `'wait'`.\n", + "- The \"`X`\" in \"`jgz X Y`\" might be an integer, not a register name, so use `vx = value(p.regs, x)`. I was stuck for a *long* time before I realized this. Finally I tried the strategy of *look carefully at the input*. I noticed the instruction `\"jgz 1 3\"`, and it was a simple change to make the program work." ] }, { @@ -2857,26 +2890,26 @@ } ], "source": [ - "def step18(program, p):\n", - " \"Run one instruction in program, with state variables in p.\"\n", + "def step18(program, Qs, p):\n", + " \"Execute one instruction in program, using state variables in p.\"\n", " if p.pc < 0 or p.pc > len(program):\n", " p.status = 'end'\n", " else:\n", " instr = program[p.pc]\n", " op, x, y = instr[0], instr[1], instr[-1]\n", " vx, vy = value(p.regs, x), value(p.regs, y)\n", - " if op == 'snd': p.Qs[1-p.p].append(vy); p.sends += 1\n", + " if op == 'snd': Qs[1-p.id].append(vy); p.sends += 1\n", " elif op == 'set': p.regs[x] = vy\n", " elif op == 'add': p.regs[x] += vy\n", " elif op == 'mul': p.regs[x] *= vy\n", " elif op == 'mod': p.regs[x] %= vy\n", " elif op == 'jgz' and vx > 0: p.pc += vy - 1\n", " elif op == 'rcv': \n", - " if not p.Qs[p.p]:\n", + " if not Qs[p.id]:\n", " p.status = 'wait'\n", - " return\n", + " return # don't update pc; try again next time\n", " else:\n", - " p.regs[x] = p.Qs[p.p].popleft()\n", + " p.regs[x] = Qs[p.id].popleft()\n", " p.status = 'run'\n", " p.pc += 1\n", " \n", @@ -2894,67 +2927,34 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "At first I was confused; I thought this was a maze-following problem with choices of which direction to turn. Actually, the direction is always determined: keep going in the current direction as long as possible, but when we hit a `'+'` character, search for another direction to go in (there will only be one, but we have to try all the possibilities to find it). Leave breadcrumbs (the `'.'` character) so that we don't back up along a previously-followed path. Collect all the alphabetic characters into `result`. As in Day 14, the grid, `G`, is surrounded by space characters so that we don't have to worry about `(x, y)` going off the edge." + "At first I was confused; I thought this was a maze-following problem where I had to make a choice of directions at every turn. Actually, the direction is always determined: keep going in the current direction as long as possible, but when we hit a `'+'` character, find the new direction to go in (there will only be one possibility). Leave breadcrumbs (the `'.'` character) so that we don't back up along a previously-followed path. As in Day 14, the grid is surrounded by a border of space characters so that we don't have to worry about `(x, y)` going off the edge." ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'VEBTPXCHLI'" - ] - }, - "execution_count": 83, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "diagram = Input(19).read().splitlines()\n", + "diagram = Inputstr(19)\n", "\n", - "def path_follow(diagram):\n", - " \"Follow -|+ lines, and collect letters along the way.\"\n", - " result = []\n", - " G = surround(diagram)\n", - " x, y = G[1].index('|'), 1\n", + "def follow_tubes(diagram):\n", + " \"Follow [-+|] lines, yielding characters along the path.\"\n", + " grid = border(' ', diagram.splitlines())\n", + " x, y = grid[1].index('|'), 1\n", " dx, dy = 0, 1\n", - " while G[y][x] != ' ':\n", - " c = G[y][x]\n", - " if c.isalpha():\n", - " result.append(c) # Collect a letter\n", - " elif c == '+':\n", - " dx, dy = new_direction(G, x, y)\n", - " G[y][x] = '.' # Leave a breadcrumb\n", + " while grid[y][x] != ' ':\n", + " yield grid[y][x]\n", + " if grid[y][x] == '+':\n", + " dx, dy = new_direction(grid, x, y)\n", + " grid[y][x] = '.' # Leave a breadcrumb\n", " x += dx; y += dy\n", - " return cat(result)\n", - " \n", - "def surround(grid, fill=' '):\n", - " \"Put fill characters as a border all around grid.\"\n", - " rows = [[fill] + list(row) + [fill] \n", - " for row in grid]\n", - " empty = [fill] * len(rows[0])\n", - " return [empty] + rows + [empty]\n", - "\n", - "def new_direction(G, x, y):\n", + " \n", + "def new_direction(grid, x, y):\n", " \"Find a direction that continues the path.\"\n", " for (dx, dy) in (UP, DOWN, RIGHT, LEFT):\n", - " if G[y+dy][x+dx] not in (' ', '.'):\n", - " return dx, dy\n", - "\n", - "path_follow(diagram)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Part Two**\n", - "\n", - "This is a surprisingly easy Part Two: all I have to do is manage a `steps += 1` in the loop to return the total number of steps taken." + " if grid[y+dy][x+dx] not in (' ', '.'):\n", + " return dx, dy" ] }, { @@ -2965,7 +2965,7 @@ { "data": { "text/plain": [ - "('VEBTPXCHLI', 18702)" + "'VEBTPXCHLI'" ] }, "execution_count": 84, @@ -2974,25 +2974,161 @@ } ], "source": [ - "def path_follow2(diagram):\n", - " \"Follow -|+ lines, collect letters along the way, return (letters, steps).\"\n", - " result = []\n", - " steps = 0\n", - " G = surround(diagram)\n", - " x, y = G[1].index('|'), 1\n", - " dx, dy = 0, 1\n", - " while G[y][x] != ' ':\n", - " steps += 1\n", - " c = G[y][x]\n", - " if c.isalpha(): \n", - " result.append(c) # Collect a letter\n", - " elif c == '+':\n", - " dx, dy = new_direction(G, x, y)\n", - " G[y][x] = '.' # Leave a breadcrumb\n", - " x += dx; y += dy\n", - " return cat(result), steps\n", + "cat(filter(str.isalpha, follow_tubes(diagram)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's the right answer.\n", "\n", - "path_follow2(diagram)" + "**Part Two**\n", + "\n", + "This is a surprisingly easy Part Two; I already generated the characters in the path; all I have to do is count them: " + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "18702" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "length(follow_tubes(diagram))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Day 20](https://adventofcode.com/2017/day/20): Particle Swarm\n", + "\n", + "I'll create structures for particles, each will have fields for particle's number (`id`), position (`p`), velocity(`v`), and acceleration (`a`):" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Struct(a=(-7, 8, -10), id=0, p=(1199, -2918, 1457), v=(-13, 115, -8)),\n", + " Struct(a=(-6, -5, 6), id=1, p=(2551, 2418, -1471), v=(-106, -108, 39)),\n", + " Struct(a=(-6, 2, -9), id=2, p=(-73, 1626, 1321), v=(58, -118, -8)),\n", + " Struct(a=(3, 3, 11), id=3, p=(-3297, -894, -551), v=(183, 31, -61)),\n", + " Struct(a=(7, -12, -1), id=4, p=(-1425, 4298, 617), v=(32, -166, -32))]" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def particles(lines=list(Input(20))):\n", + " \"Parse the list of particles.\"\n", + " return [Particle(id, line) for id, line in enumerate(lines)]\n", + "\n", + "def Particle(id, line):\n", + " \"Parse a single Particle.\"\n", + " ns = Integers(line) # Assumes format \"p=<1,8,4>, v=<3,1,-8>, a=<7,8,-10>\" \n", + " return Struct(id=id, p=ns[0:3], v=ns[3:6], a=ns[6:9])\n", + "\n", + "particles()[:5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "I'm not quite sure how to determine what \"in the long run\" means, so I'll just interpret it as meaning \"after 1000 time steps.\" On each step we update velocity and position of each particle. At the end, we determine the id number of the particle closest to the origin. Note that `evolve` generates an infinite sequence of particles, and we use `nth` to pick out the 1000th generation." + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "243" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def evolve(particles):\n", + " \"Continually update particles, yielding them after each time step.\"\n", + " while True:\n", + " yield particles\n", + " for p in particles:\n", + " p.v = add(p.v, p.a)\n", + " p.p = add(p.p, p.v)\n", + " \n", + "def add(A, B): \n", + " \"Add two n-dimensional vectors.\"\n", + " return mapt(sum, zip(A, B))\n", + "\n", + "def closest(particles):\n", + " \"Find the particle closest to origin.\"\n", + " return min(particles, key=lambda p: sum(map(abs, p.p)))\n", + "\n", + "# Answer: the id of the particle closest to origin in the 1000th generation of `evolve`\n", + "closest(nth(evolve(particles()), 1000)).id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Part Two**\n", + "\n", + "I can still use `evolve` unchanged, and I will add the function `remove_collisions` to eliminate particles that are in the same position as another particle. I use `map` to apply this to every generation. Note that `remove_collisions` both mutates the argument, `particles`, and also returns it. " + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "648" + ] + }, + "execution_count": 88, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def remove_collisions(particles):\n", + " \"Mutate (and return) particles, keep only ones that have a unique position.\"\n", + " poscount = Counter(p.p for p in particles)\n", + " particles[:] = [p for p in particles if poscount[p.p] == 1]\n", + " return particles\n", + " \n", + "# Answer: remove collisions from every generation of evolving particles, \n", + "# select the 1000th generation, and say how many particles are in that generation.\n", + "len(nth(map(remove_collisions, evolve(particles())), 1000))" ] }, { @@ -3006,15 +3142,15 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 58.9 s, sys: 125 ms, total: 59 s\n", - "Wall time: 59.1 s\n" + "CPU times: user 46.8 s, sys: 62.8 ms, total: 46.9 s\n", + "Wall time: 46.9 s\n" ] } ], @@ -3062,27 +3198,29 @@ " spinlock3(N=50*10**6)[1], 6154117)\n", "day(18, run18(program18), 7071, \n", " run18_2(program18)[1].sends, 8001)\n", - "day(19, path_follow(diagram), 'VEBTPXCHLI', \n", - " path_follow2(diagram)[1], 18702)" + "day(19, cat(filter(str.isalpha, follow_tubes(diagram))), 'VEBTPXCHLI', \n", + " quantify(follow_tubes(diagram)), 18702)\n", + "day(20, closest(nth(evolve(particles()), 1000)).id, 243,\n", + " len(nth(map(remove_collisions, evolve(particles())), 1000)), 648)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "And here is a plot of the time taken to completely solve both parts of each puzzle each day, for me, the first person to finish, and the hundredth person. On days when I started late, the times are estimates, not exact (these include days 1, 3, 8, 13, 14, 17, 18)." + "And here is a plot of the time taken to program solutions to both parts of each puzzle each day, for me, the first person to finish, and the hundredth person. On days when I started late, the times are estimates, not exact (these include days 1, 3, 8, 13, 14, 17, 18)." ] }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 90, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\nSUVORK5CYII=\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -3095,14 +3233,14 @@ " X = ints(1, len(times[0]) - 2)\n", " for (label, mark, *Y) in times:\n", " plt.plot(X, Y, mark, label=label)\n", - " plt.xlabel('Day Number'); plt.ylabel('Minutes to Solve Both')\n", + " plt.xlabel('Day Number'); plt.ylabel('Minutes to Solve Both Parts')\n", " plt.legend(loc='upper left')\n", "\n", "x = None\n", "plot_times([\n", - " ('Me', 'd:', 4, 6, 20, 5, 12, 30, 33, 10, 21, 40, 13, 12, 30, 41, 13, 64, 54, 74, 50),\n", - " ('100th', 'v:', 6, 6, 23, 4, 5, 9, 25, 8, 12, 25, 12, 9, 22, 25, 10, 27, 16, 41, 18),\n", - " ('1st', '^:', 1, 1, 4, 1, 2, 3, 10, 3, 4, 6, 3, 2, 6, 5, 2, 5, 5, 10, 5)])" + " ('Me', 'd:', 4, 6, 20, 5, 12, 30, 33, 10, 21, 40, 13, 12, 30, 41, 13, 64, 54, 74, 50, 18),\n", + " ('100th', 'v:', 6, 6, 23, 4, 5, 9, 25, 8, 12, 25, 12, 9, 22, 25, 10, 27, 16, 41, 18, 21),\n", + " ('1st', '^:', 1, 1, 4, 1, 2, 3, 10, 3, 4, 6, 3, 2, 6, 5, 2, 5, 5, 10, 5, 7)])" ] } ],