Add files via upload

This commit is contained in:
Peter Norvig 2017-12-08 22:08:54 -08:00 committed by GitHub
parent 3f9d45a87c
commit eca428fe71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -19,17 +19,19 @@
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
"collapsed": false
},
"outputs": [],
"source": [
"# Python 3.x Utility Functions\n",
"\n",
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import re\n",
"import numpy as np\n",
"import math\n",
"import random\n",
"import urllib.request\n",
"\n",
"from collections import Counter, defaultdict, namedtuple, deque, abc, OrderedDict\n",
"from functools import lru_cache\n",
@ -40,6 +42,8 @@
"identity = lambda x: x\n",
"letters = 'abcdefghijklmnopqrstuvwxyz'\n",
"\n",
"cache = lru_cache(None)\n",
"\n",
"cat = ''.join\n",
"\n",
"Ø = frozenset() # Empty set\n",
@ -161,6 +165,11 @@
"def mapt(fn, *args): \n",
" \"Do a map, and make the results into a tuple.\"\n",
" return tuple(map(fn, *args))\n",
"\n",
"def most_common(seq):\n",
" \"The item that appears most frequently in sequence.\"\n",
" [(item, count)] = Counter(seq).most_common(1)\n",
" return item\n",
" \n",
"################ Math Functions\n",
" \n",
@ -188,6 +197,13 @@
" result *= n\n",
" return result\n",
"\n",
"import operator as op\n",
"\n",
"operations = {'>': op.gt, '>=': op.ge, '==': op.eq,\n",
" '<': op.lt, '<=': op.le, '!=': op.ne,\n",
" '+': op.add, '-': op.sub, '*': op.mul, \n",
" '/': op.truediv, '**': op.pow}\n",
"\n",
"################ 2-D points implemented using (x, y) tuples\n",
"\n",
"def X(point): x, y = point; return x\n",
@ -264,7 +280,9 @@
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -359,7 +377,9 @@
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -388,7 +408,9 @@
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -450,7 +472,9 @@
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -477,7 +501,9 @@
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -543,7 +569,9 @@
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -598,7 +626,9 @@
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -618,7 +648,9 @@
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -663,7 +695,9 @@
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -690,7 +724,9 @@
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -719,7 +755,9 @@
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -750,7 +788,9 @@
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -775,7 +815,7 @@
"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--the top 20 took less than two minutes each."
"That was easy, but the leaders were three times faster than me."
]
},
{
@ -790,7 +830,9 @@
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -821,7 +863,9 @@
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -860,7 +904,9 @@
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
@ -914,7 +960,9 @@
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -955,7 +1003,9 @@
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"banks = vector('4\t10\t4\t1\t8\t4\t9\t14\t5\t1\t14\t15\t0\t15\t3\t5')\n",
@ -983,7 +1033,9 @@
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -1003,7 +1055,9 @@
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -1030,7 +1084,9 @@
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -1057,7 +1113,9 @@
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -1086,7 +1144,9 @@
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
@ -1102,6 +1162,432 @@
"source": [
"realloc2(banks)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# [Day 7](https://adventofcode.com/2017/day/7): Memory Reallocation "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First I'll read the data into two dicts as follows: the input line:\n",
"\n",
" tcmdaji (40) -> wjbdxln, amtqhf\n",
" \n",
"creates:\n",
"\n",
" weight['tcmdaji'] = 40\n",
" above['tcmdaji'] = ['wjbdxln', 'amtqhf']"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def towers(lines):\n",
" \"Return (weight, above) dicts.\"\n",
" weight = {}\n",
" above = {}\n",
" for line in lines:\n",
" name, w, *rest = re.findall(r'\\w+', line)\n",
" weight[name] = int(w)\n",
" above[name] = rest\n",
" return weight, above\n",
"\n",
"weight, above = towers(Input(7))\n",
"\n",
"programs = set(above)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now the root progam is the one that is not above anything:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{'wiapj'}"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"programs - set(flatten(above.values()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Part Two:**\n",
"\n",
"A program is *wrong* if it is the bottom of a tower that is a different weight from all its sibling towers:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def wrong(p): return tower_weight(p) not in map(tower_weight, siblings(p))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we define `tower_weight`, `siblings`, and the `below` dict:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def tower_weight(p): return weight[p] + sum(map(tower_weight, above[p]))\n",
"\n",
"def siblings(p): \n",
" \"The other programs at the same level as this one.\"\n",
" return [] if p not in below else [s for s in above[below[p]] if s != p]\n",
"\n",
"below = {a: b for b in programs for a in above[b]}"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{'eionkb', 'lsire', 'wiapj', 'ycpcv'}"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"set(filter(wrong, programs))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So these four programs are wrong. Which one should we correct? The one that is wrong, and has no wrong program above it:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'eionkb'"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def wrongest(programs):\n",
" return first(p for p in programs\n",
" if wrong(p) \n",
" and not any(wrong(p2) for p2 in above[p]))\n",
"\n",
"wrongest(programs) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now what should we correct it to? To the weight that makes it the same weight as sibling towers:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1072"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def correct(p):\n",
" \"Return the weight that would make p's tower's weight the same as its sibling towers.\"\n",
" delta = tower_weight(first(siblings(p))) - tower_weight(p) \n",
" return weight[p] + delta\n",
"\n",
"correct(wrongest(programs))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"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."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"6828"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"program = array(Input(8))\n",
"\n",
"def run8(program):\n",
" \"Run the program and return final value of registers.\"\n",
" registers = defaultdict(int)\n",
" for (r, inc, delta, _if, r2, cmp, amount) in program:\n",
" if operations[cmp](registers[r2], amount):\n",
" registers[r] += delta * (+1 if inc == 'inc' else -1)\n",
" return registers\n",
"\n",
"max(run8(program).values())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Part Two:**\n",
"\n",
"Here I modify the interpreter to keep track of the highest value of any register at any time."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"7234"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def run82(program):\n",
" registers = defaultdict(int)\n",
" highest = 0\n",
" for r, inc, delta, _if, r2, cmp, amount in program:\n",
" if operations[cmp](registers[r2], amount):\n",
" registers[r] += delta * (+1 if inc == 'inc' else -1)\n",
" highest = max(highest, registers[r])\n",
" return highest\n",
"\n",
"run82(program)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# [Day 9](https://adventofcode.com/2017/day/9): Stream Processing\n",
"\n",
"For this problem I could have a complex finite-state machine that handles all the characters `'{<!>}'`, but I think it is easier to clean up the garbage first:"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'{{{{{{{},},{{},}},{{{{}},{{{{{}}},{}},},{{{{},{,{{{}}}}},},{{{}},{{}}}}},{{,{}},{{},},{}}}},{{{{{}}},{}},{{{{},},{}},{{{}},{{{},},{}},{}},{{}}},{{,},{{{}},{{{{}},{{{},},{}}},{{{{},},{}}},{{{}},{{}}}}}}},{{{},{{}},{{{{},{}}},}},{{{}},{}},{{},{{},{}}},{{{}},{{}}}}},{{{{},{}}},{{},{{{{},{}},{{{},{{}}}}}},{{}}},{},{{{}}}},{{{{},{{{},{{},{}}}},{{{{},{}},{{}}}}}},{{{},{{{{}},{{},{}}},{{{,},{{}}},{{}},{{}}},{{}},{{{{},{},{{}}},{{{{}},{{{{{},{}}},{{}}},{,{}},{}},{}},{},{{{},{}}}},{{{{{},},{}},{,},{{}}},{,},{{{},},{{}}}},{{,},{{{{}},{}},{}},{{{},{}}}}},{{{},},{{},{{}}}},{},{{{{{},{}},{},{{}}},{,},{{},}},{{},{}},{{{}},{}}}}},{{{},},{{},{,{{,{}},}}}}},{},{{},{{},{}}},{{},{,},{,{}}}}},{{{{{{},{}}},{,{}},{{},{,{{}}}}},{{},{}}},{{{}},{{},{}},{{}}},{{{},{{},{}}},{{,}},{{,{}},{{{}},{}},{,{,{}}}}},{{{},{}}}},{{{{{}}},{}},{{{},{{{}},{}},{{},}},{{{},},{{,{}}},{{},{{},{}}}},{{{{}}}},{{{,},{}},{},{{},{{{},},{}}},{{{{{}},{{{},{{},}},}},{{},{}},{,{{},{}}}},{{,{}},{{,{}},}},{{,{}}}}}}}},{{{{{},},{{{{},{}}}}},{{{},},{{,{}},{{},{,{}}}}},{{{},{{{{}}},{}}},{{},{},{,}},{{},{{},}},{{{{}},{}},{{},{}},{{{{}}},{}}}},{{{}},{{},{}}}},{{{{{{},{}},{}},{{,},},{{,}}}},{},{},{{{,{}},{{},{}},{{{}},}},{{},{,},{}},{{{},{}}},{{{{}},},{{},},{{}}}}},{{{{{}},{,},{}},{{},{{{{{},},{{{},{}}}},{{},{{},}}},{},{{{{},{}},{}}}}}},{{},{{},{}}},{{{}},{{},},{,{{}}}}}},{{},{{{},{{}},{,{,}}},{{{}}},{{{{},{}},}}},{{{{,{}},{{,{}},{}}},{{{,{,}},{,}},{}},{{{{{},{}}},{{},{}},{{},{{{},}}}},{{{}}},{{{},{{},{}}}}},{}},{{}}},{{{,{{},{}}},{{},}},{{{}},{}},{{{},{}},{{{{}},{{},},{{{{}},{},{{{,{}},{}}}}}}},{,}},{{},{{{},{}},}}}},{{{{{{,{}},{{}},{{}}},{{{{{},{}},{{},{}},{{}}},{{}},{}},{{},},{,{}}},{{}},{{{}},{,},{,{}}}},{{{{}}},{{{,{}}},{{{}},{,}},{{},{{{}},{{},}},{{{}},{{},}},{{{,},{{{},{}},{}},{}},{{{}},{{},}},{{{{{{{},}}}},{{{,{{}}},{}},{,},{{{{}}},{{}}}},{{{}},{,{{},{}}}}}}}}},{{{}},{{},{}}},{{,},{,{,{}}}}},{{{}}},{{},{{}},{,}}},{{{{{{{},},{},{{{,{}},{}},}}},{},{{{}}}},{{,},{{,{}}},{{{},},}},{{{}},{{{,}},{}},{{}}}},{{},{,{}},{{},{{}}}},{{}},{{{},{{},},{}},{{}},{{},{}}}},{{{{}},{{},}},{{{{}},{{},{}}},{}},{{{{}},{},{{{{,{}}},{}}}},{{,{}},{{{{{},},{{{{}}},{,{}},{{}}}},{,},{}},{{}}},{{},}},{{{{},{{,{}},}},{{}},{{},}}},{{{},{{,{}}}},{{{},},},{{}}}}}},{{{{},},{{}}},{{{{{},{}}},{{,}}},{}},{{},{},{}}},{{{{{}},{{}},{}},{{},{{},{{{}},{{,},{{{},{}},{}},{{},}},{}},{{{{},{{{}},{{}}}}}},{{{},{,{{}}}},{{{,}}},{{{{{{},},{{{}},}},{}},{{}},{{{{}},{,{}}},}},{{{,}},{{{{}}},{},{{},}},{{{,{}},{,{}}},{{{}},{{{{},{}}},{{{{,},},}}},{{}}},{}}},{{},{{,{{},}},{{},}},{{{},{}},}},{{{},{}},{,{}},{,}}},{{{{},{{,{}}}}},{{}},{,}}}},{{,},{{},{}},{}},{{{{{{},{}},{}},{{{{},{}},{{}}},{,{{},{}}},{{},{,}}}},{{},{}}},{,},{{{},{}},{{},{}}}}},{{}},{{{{{{}},{{},{}},{{{},{{}}},{}}}},{{{{{},{{}}},{}}}},{{{}},{},{,{}}},{{{{}},{}},{{},{{{{},{{}}}}},{{{},{{}},{,{}}}}}}}}},{{{{{}},},{},{}},{}}},{{},{{{,{}},{,},{{}}},{}},{{,{}},{{{},},{}},{{{}},}},{{{{{}},},{{{,{}},},{,},{{{}},}},{}},{{{{}},{}},{{}}}}}},{{{{{,{}},{},{}},{{}}}},{{{,},{{{},{}}},{{{{},{{{},}}},{}},{{{},},{{,}}},{,{}}}},{{{{},{}},},{{,{{}}}},{{},{}}},{{{},}}},{},{{{{},},{{{}},{}},{{{{{}},{{}}},{}}}},{{{,},{{},{}}},{{},{{}}}},{{{},{{},{}}},{{{},}},{{{}},{},{,{}}},{{{},{{},{}},{,{}}}}}}}}\\n'"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"text1 = Input(9).read() # Read text\n",
"text2 = re.sub(r'!.', '', text1) # Delete canceled characters\n",
"text3 = re.sub(r'<.*?>', '', text2) # Delete garbage\n",
"text3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now I can deal with nested braces (which can't be handled with regular expressions):"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"9662"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def total_score(text):\n",
" \"Total of group scores; each group scores one more than the group it is nested in.\"\n",
" total = 0\n",
" outer = [0] # Stack of scores of groups nested outside current group\n",
" for c in text:\n",
" if c == '{':\n",
" score = outer[-1] + 1\n",
" total += score\n",
" outer.append(score)\n",
" elif c == '}':\n",
" outer.pop()\n",
" return total\n",
"\n",
"total_score(text3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Part Two:**\n",
"\n",
"At first I thought that the amount of garbage is just the difference in lengths of `text2` and `text3`:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5989"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(text2) - len(text3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But that turned out to be wrong; that counts all of `'<...>'`, whereas I'm not suppossed to count the opening and closing angle brackets, just the `'...'` in the middle. So that would be:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"4903"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"text4 = re.sub(r'<.*?>', '<>', text2) # Delete inner garbage\n",
"\n",
"len(text2) - len(text4)"
]
}
],
"metadata": {
@ -1120,7 +1606,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.3"
"version": "3.6.0"
}
},
"nbformat": 4,