My Advent of Code solutions in Python.
kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code
python
1import re
2import math
3import operator
4from functools import total_ordering
5
6
7LETTERS = [x for x in 'abcdefghijklmnopqrstuvwxyz']
8VOWELS = {'a', 'e', 'i', 'o', 'u'}
9CONSONANTS = set(x for x in LETTERS if x not in VOWELS)
10
11
12def parse_line(regex, line):
13 ret = []
14 for match in re.match(regex, line).groups():
15 try:
16 ret.append(int(match))
17 except ValueError:
18 ret.append(match)
19
20 return ret
21
22
23def new_table(val, width, height):
24 return [[val for _ in range(width)] for _ in range(height)]
25
26
27def mul(lst):
28 """Like sum(), but for multiplication."""
29 return reduce(operator.mul, lst, 1) # NOQA
30
31
32def chunks(l, n):
33 """Yield successive n-sized chunks from l."""
34 for i in range(0, len(l), n):
35 yield l[i:i + n]
36
37
38def factors(n):
39 """Returns the factors of n."""
40 return sorted(
41 x for tup in (
42 [i, n // i] for i in range(1, int(n ** 0.5) + 1)
43 if n % i == 0)
44 for x in tup)
45
46
47def memoize(f):
48 """Simple dictionary-based memoization decorator"""
49 cache = {}
50
51 def _mem_fn(*args):
52 if args not in cache:
53 cache[args] = f(*args)
54 return cache[args]
55
56 _mem_fn.cache = cache
57 return _mem_fn
58
59
60def _eratosthenes(n):
61 """http://stackoverflow.com/a/3941967/239076"""
62 # Initialize list of primes
63 _primes = [True] * n
64
65 # Set 0 and 1 to non-prime
66 _primes[0] = _primes[1] = False
67
68 for i, is_prime in enumerate(_primes):
69 if is_prime:
70 yield i
71
72 # Mark factors as non-prime
73 for n in xrange(i * i, n, i): # NOQA
74 _primes[n] = False
75
76
77def primes(n):
78 """Return a list of primes from [2, n)"""
79 return list(_eratosthenes(n))
80
81
82@total_ordering
83class Point:
84 """Simple 2-dimensional point."""
85 def __init__(self, x, y):
86 self.x = x
87 self.y = y
88
89 def __add__(self, other):
90 return Point(self.x + other.x, self.y + other.y)
91
92 def __sub__(self, other):
93 return Point(self.x - other.x, self.y - other.y)
94
95 def __mul__(self, n):
96 return Point(self.x * n, self.y * n)
97
98 def __div__(self, n):
99 return Point(self.x / n, self.y / n)
100
101 def __neg__(self):
102 return Point(-self.x, -self.y)
103
104 def __eq__(self, other):
105 return self.x == other.x and self.y == other.y
106
107 def __ne__(self, other):
108 return not self == other
109
110 def __lt__(self, other):
111 return self.manhattan < other.manhattan
112
113 def __str__(self):
114 return "({}, {})".format(self.x, self.y)
115
116 def __hash__(self):
117 return hash(tuple((self.x, self.y)))
118
119 @property
120 def manhattan(self):
121 return abs(self.x) + abs(self.y)
122
123 @property
124 def distance(self):
125 return math.sqrt(self.x ** 2 + self.y ** 2)