Add files via upload
This commit is contained in:
parent
d2673fb0bd
commit
10324c5a8a
252
ipynb/Advent 2017.ipynb
Normal file
252
ipynb/Advent 2017.ipynb
Normal file
@ -0,0 +1,252 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 89,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Python 3.x\n",
|
||||
"\n",
|
||||
"import re\n",
|
||||
"import numpy as np\n",
|
||||
"import math\n",
|
||||
"import urllib.request\n",
|
||||
"\n",
|
||||
"from collections import Counter, defaultdict, namedtuple, deque\n",
|
||||
"from functools import lru_cache\n",
|
||||
"from itertools import permutations, combinations, chain, cycle, product, islice, count as count_from\n",
|
||||
"from heapq import heappop, heappush\n",
|
||||
"\n",
|
||||
"identity = lambda x: x\n",
|
||||
"letters = 'abcdefghijklmnopqrstuvwxyz'\n",
|
||||
"\n",
|
||||
"cat = ''.join\n",
|
||||
"\n",
|
||||
"Ø = frozenset() # Empty set\n",
|
||||
"inf = float('inf')\n",
|
||||
"BIG = 10 ** 999\n",
|
||||
"\n",
|
||||
"def Input(day, year=2017):\n",
|
||||
" \"Open this day's input file.\"\n",
|
||||
" filename = 'data/advent{}/input{}.txt'.format(year, day)\n",
|
||||
" try:\n",
|
||||
" return open(filename)\n",
|
||||
" except FileNotFoundError:\n",
|
||||
" return urllib.request.urlopen(\"http://norvig.com/ipython/\" + filename)\n",
|
||||
"\n",
|
||||
"################ Functions on Iterables\n",
|
||||
"\n",
|
||||
"def first(iterable, default=None): return next(iter(iterable), default)\n",
|
||||
"\n",
|
||||
"def first_true(iterable, pred=None, default=None):\n",
|
||||
" \"\"\"Returns the first true value in the iterable.\n",
|
||||
" If no true value is found, returns *default*\n",
|
||||
" If *pred* is not None, returns the first item\n",
|
||||
" for which pred(item) is true.\"\"\"\n",
|
||||
" # first_true([a,b,c], default=x) --> a or b or c or x\n",
|
||||
" # first_true([a,b], fn, x) --> a if fn(a) else b if fn(b) else x\n",
|
||||
" return next(filter(pred, iterable), default)\n",
|
||||
"\n",
|
||||
"def nth(iterable, n, default=None):\n",
|
||||
" \"Returns the nth item of iterable, or a default value\"\n",
|
||||
" return next(islice(iterable, n, None), default)\n",
|
||||
"\n",
|
||||
"def upto(iterable, maxval):\n",
|
||||
" \"From a monotonically increasing iterable, generate all the values <= maxval.\"\n",
|
||||
" # Why <= maxval rather than < maxval? In part because that's how Ruby's upto does it.\n",
|
||||
" return takewhile(lambda x: x <= maxval, iterable)\n",
|
||||
"\n",
|
||||
"def groupby(iterable, key=identity):\n",
|
||||
" \"Return a dict of {key(item): [items...]} grouping all items in iterable by keys.\"\n",
|
||||
" groups = defaultdict(list)\n",
|
||||
" for item in iterable:\n",
|
||||
" groups[key(item)].append(item)\n",
|
||||
" return groups\n",
|
||||
"\n",
|
||||
"def grouper(iterable, n, fillvalue=None):\n",
|
||||
" \"\"\"Collect data into fixed-length chunks:\n",
|
||||
" grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx\"\"\"\n",
|
||||
" args = [iter(iterable)] * n\n",
|
||||
" return zip_longest(*args, fillvalue=fillvalue)\n",
|
||||
"\n",
|
||||
"def overlapping(iterable, n):\n",
|
||||
" \"\"\"Generate all (overlapping) n-element subsequences of iterable.\n",
|
||||
" overlapping('ABCDEFG', 3) --> ABC BCD CDE DEF EFG\"\"\"\n",
|
||||
" if isinstance(iterable, abc.Sequence):\n",
|
||||
" yield from (iterable[i:i+n] for i in range(len(iterable) + 1 - n))\n",
|
||||
" else:\n",
|
||||
" result = deque(maxlen=n)\n",
|
||||
" for x in iterable:\n",
|
||||
" result.append(x)\n",
|
||||
" if len(result) == n:\n",
|
||||
" yield tuple(result)\n",
|
||||
" \n",
|
||||
"def pairwise(iterable):\n",
|
||||
" \"s -> (s0,s1), (s1,s2), (s2, s3), ...\"\n",
|
||||
" return overlapping(iterable, 2)\n",
|
||||
"\n",
|
||||
"def sequence(iterable, type=tuple):\n",
|
||||
" \"Coerce iterable to sequence: leave it alone if it is already a sequence, else make it of type.\"\n",
|
||||
" return iterable if isinstance(iterable, abc.Sequence) else type(iterable)\n",
|
||||
"\n",
|
||||
"def join(iterable, sep=''):\n",
|
||||
" \"Join the items in iterable, converting each to a string first.\"\n",
|
||||
" return sep.join(map(str, iterable))\n",
|
||||
" \n",
|
||||
"def powerset(iterable):\n",
|
||||
" \"Yield all subsets of items.\"\n",
|
||||
" items = list(iterable)\n",
|
||||
" for r in range(len(items)+1):\n",
|
||||
" for c in combinations(items, r):\n",
|
||||
" yield c\n",
|
||||
" \n",
|
||||
"def quantify(iterable, pred=bool):\n",
|
||||
" \"Count how many times the predicate is true.\"\n",
|
||||
" return sum(map(pred, iterable))\n",
|
||||
"\n",
|
||||
"def shuffled(iterable):\n",
|
||||
" \"Create a new list out of iterable, and shuffle it.\"\n",
|
||||
" new = list(iterable)\n",
|
||||
" random.shuffle(new)\n",
|
||||
" return new\n",
|
||||
" \n",
|
||||
"flatten = chain.from_iterable\n",
|
||||
" \n",
|
||||
"class Set(frozenset):\n",
|
||||
" \"A frozenset, but with a prettier printer.\"\n",
|
||||
" def __repr__(self): return '{' + join(sorted(self), ', ') + '}'\n",
|
||||
" \n",
|
||||
"def canon(items, typ=None):\n",
|
||||
" \"Canonicalize these order-independent items into a hashable canonical form.\"\n",
|
||||
" typ = (typ or (cat if isinstance(items, str) else tuple))\n",
|
||||
" return typ(sorted(items))\n",
|
||||
" \n",
|
||||
"################ Math\n",
|
||||
" \n",
|
||||
"def transpose(matrix): return tuple(zip(*matrix))\n",
|
||||
"\n",
|
||||
"def isqrt(n):\n",
|
||||
" \"Integer square root (rounds down).\"\n",
|
||||
" return int(n ** 0.5)\n",
|
||||
"\n",
|
||||
"def ints(start, end):\n",
|
||||
" \"The integers from start to end, inclusive. Equivalent to range(start, end+1)\"\n",
|
||||
" return range(start, end + 1)\n",
|
||||
"\n",
|
||||
"def floats(start, end, step=1.0):\n",
|
||||
" \"Yields start, start+step, start+2*step, ... up to (maybe including) end.\"\n",
|
||||
" m = (1.0 if step >= 0 else -1.0)\n",
|
||||
" while start * m <= end * m:\n",
|
||||
" yield start\n",
|
||||
" start += step\n",
|
||||
" \n",
|
||||
"def multiply(numbers):\n",
|
||||
" \"Multiply all the numbers together.\"\n",
|
||||
" result = 1\n",
|
||||
" for n in numbers:\n",
|
||||
" result *= n\n",
|
||||
" return result\n",
|
||||
"\n",
|
||||
"################ 2-D points implemented using (x, y) tuples\n",
|
||||
"\n",
|
||||
"def X(point): x, y = point; return x\n",
|
||||
"def Y(point): x, y = point; return y\n",
|
||||
"\n",
|
||||
"def neighbors4(point): \n",
|
||||
" \"The four neighboring squares.\"\n",
|
||||
" x, y = point\n",
|
||||
" return ( (x, y-1),\n",
|
||||
" (x-1, y), (x+1, y), \n",
|
||||
" (x, y+1))\n",
|
||||
"\n",
|
||||
"def neighbors8(point): \n",
|
||||
" \"The eight neighboring squares.\"\n",
|
||||
" x, y = point \n",
|
||||
" return ((x-1, y-1), (x, y-1), (x+1, y-1),\n",
|
||||
" (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=(0, 0)): \n",
|
||||
" \"Manhatten distance between two points.\"\n",
|
||||
" return abs(X(p) - X(q)) + abs(Y(p) - Y(q))\n",
|
||||
"\n",
|
||||
"def distance(p, q=(0, 0)): \n",
|
||||
" \"Hypotenuse distance between two points.\"\n",
|
||||
" return math.hypot(X(p) - X(q), Y(p) - Y(q))\n",
|
||||
"\n",
|
||||
"################ Debugging \n",
|
||||
"\n",
|
||||
"def trace1(f):\n",
|
||||
" \"Print a trace of the input and output of a function on one line.\"\n",
|
||||
" def traced_f(*args):\n",
|
||||
" result = f(*args)\n",
|
||||
" print('{}({}) = {}'.format(f.__name__, ', '.join(map(str, args)), result))\n",
|
||||
" return result\n",
|
||||
" return traced_f\n",
|
||||
"\n",
|
||||
"def grep(pattern, iterable):\n",
|
||||
" \"Print lines from iterable that match pattern.\"\n",
|
||||
" for line in iterable:\n",
|
||||
" if re.search(pattern, line):\n",
|
||||
" print(line)\n",
|
||||
"\n",
|
||||
"################ A* and Breadth-First Search (we track states, not actions)\n",
|
||||
"\n",
|
||||
"def Astar(start, moves_func, h_func, cost_func=lambda s, s2: 1):\n",
|
||||
" \"Find a shortest sequence of states from start to a goal state (a state s with h_func(s) == 0).\"\n",
|
||||
" frontier = [(h_func(start), start)] # A priority queue, ordered by path length, f = g + h\n",
|
||||
" previous = {start: None} # start state has no previous state; other states will\n",
|
||||
" path_cost = {start: 0} # The cost of the best path to a state.\n",
|
||||
" Path = lambda s: ([] if (s is None) else Path(previous[s]) + [s])\n",
|
||||
" while frontier:\n",
|
||||
" (f, s) = heappop(frontier)\n",
|
||||
" if h_func(s) == 0:\n",
|
||||
" return Path(s)\n",
|
||||
" for s2 in moves_func(s):\n",
|
||||
" g = path_cost[s] + cost_func(s, s2)\n",
|
||||
" if s2 not in path_cost or g < path_cost[s2]:\n",
|
||||
" heappush(frontier, (g + h_func(s2), s2))\n",
|
||||
" path_cost[s2] = g\n",
|
||||
" previous[s2] = s\n",
|
||||
"\n",
|
||||
"def bfs(start, moves_func, goals):\n",
|
||||
" \"Breadth-first search\"\n",
|
||||
" goal_func = (goals if callable(goals) else lambda s: s in goals)\n",
|
||||
" return Astar(start, moves_func, lambda s: (0 if goal_func(s) else 1))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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.6.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
Loading…
Reference in New Issue
Block a user