My Advent of Code solutions in Python. kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add template files for 2018

+237
+29
2018/starter.py
··· 1 + import os # NOQA 2 + import sys # NOQA 3 + import re # NOQA 4 + import math # NOQA 5 + import fileinput 6 + from collections import Counter, defaultdict, deque, namedtuple # NOQA 7 + from itertools import count, product, permutations, combinations, combinations_with_replacement # NOQA 8 + 9 + from utils import parse_line, mul, all_unique, factors, memoize, primes # NOQA 10 + from utils import new_table, transposed, rotated # NOQA 11 + from utils import md5, sha256, knot_hash # NOQA 12 + from utils import Point, DIRS, DIRS_4, DIRS_8 # NOQA 13 + 14 + # Itertools Functions: 15 + # product('ABCD', repeat=2) AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD 16 + # permutations('ABCD', 2) AB AC AD BA BC BD CA CB CD DA DB DC 17 + # combinations('ABCD', 2) AB AC AD BC BD CD 18 + # combinations_with_replacement('ABCD', 2) AA AB AC AD BB BC BD CC CD DD 19 + 20 + total = 0 21 + result = [] 22 + table = new_table(None, width=2, height=4) 23 + 24 + for i, line in enumerate(fileinput.input()): 25 + line = line.strip() 26 + data = parse_line(r'', line) 27 + 28 + if i == 0: 29 + print(data)
+208
2018/utils.py
··· 1 + import re 2 + import math 3 + import hashlib 4 + import operator 5 + from functools import total_ordering 6 + 7 + 8 + LETTERS = [x for x in 'abcdefghijklmnopqrstuvwxyz'] 9 + VOWELS = {'a', 'e', 'i', 'o', 'u'} 10 + CONSONANTS = set(x for x in LETTERS if x not in VOWELS) 11 + 12 + 13 + def parse_line(regex, line): 14 + ret = [] 15 + for match in re.match(regex, line).groups(): 16 + try: 17 + ret.append(int(match)) 18 + except ValueError: 19 + ret.append(match) 20 + 21 + return ret 22 + 23 + 24 + def new_table(val, width, height): 25 + return [[val for _ in range(width)] for _ in range(height)] 26 + 27 + 28 + def transposed(matrix): 29 + """Returns the transpose of the given matrix.""" 30 + return [list(r) for r in zip(*matrix)] 31 + 32 + 33 + def rotated(matrix): 34 + """Returns the given matrix rotated 90 degrees clockwise.""" 35 + return [list(r) for r in zip(*matrix[::-1])] 36 + 37 + 38 + def mul(lst): 39 + """Like sum(), but for multiplication.""" 40 + return reduce(operator.mul, lst, 1) # NOQA 41 + 42 + 43 + def chunks(l, n): 44 + """Yield successive n-sized chunks from l.""" 45 + for i in range(0, len(l), n): 46 + yield l[i:i + n] 47 + 48 + 49 + def all_unique(lst): 50 + return len(lst) == len(set(lst)) 51 + 52 + 53 + def factors(n): 54 + """Returns the factors of n.""" 55 + return sorted( 56 + x for tup in ( 57 + [i, n // i] for i in range(1, int(n ** 0.5) + 1) 58 + if n % i == 0) 59 + for x in tup) 60 + 61 + 62 + def memoize(f): 63 + """Simple dictionary-based memoization decorator""" 64 + cache = {} 65 + 66 + def _mem_fn(*args): 67 + if args not in cache: 68 + cache[args] = f(*args) 69 + return cache[args] 70 + 71 + _mem_fn.cache = cache 72 + return _mem_fn 73 + 74 + 75 + def _eratosthenes(n): 76 + """http://stackoverflow.com/a/3941967/239076""" 77 + # Initialize list of primes 78 + _primes = [True] * n 79 + 80 + # Set 0 and 1 to non-prime 81 + _primes[0] = _primes[1] = False 82 + 83 + for i, is_prime in enumerate(_primes): 84 + if is_prime: 85 + yield i 86 + 87 + # Mark factors as non-prime 88 + for j in xrange(i * i, n, i): # NOQA 89 + _primes[j] = False 90 + 91 + 92 + def primes(n): 93 + """Return a list of primes from [2, n)""" 94 + return list(_eratosthenes(n)) 95 + 96 + 97 + def md5(msg): 98 + m = hashlib.md5() 99 + m.update(msg) 100 + return m.hexdigest() 101 + 102 + 103 + def sha256(msg): 104 + s = hashlib.sha256() 105 + s.update(msg) 106 + return s.hexdigest() 107 + 108 + 109 + def knot_hash(msg): 110 + lengths = [ord(x) for x in msg] + [17, 31, 73, 47, 23] 111 + sparse = range(0, 256) 112 + pos = 0 113 + skip = 0 114 + 115 + for _ in range(64): 116 + for l in lengths: 117 + for i in range(l // 2): 118 + x = (pos + i) % len(sparse) 119 + y = (pos + l - i - 1) % len(sparse) 120 + sparse[x], sparse[y] = sparse[y], sparse[x] 121 + 122 + pos = pos + l + skip % len(sparse) 123 + skip += 1 124 + 125 + hash_val = 0 126 + 127 + for i in range(16): 128 + res = 0 129 + for j in range(0, 16): 130 + res ^= sparse[(i * 16) + j] 131 + 132 + hash_val += res << ((16 - i - 1) * 8) 133 + 134 + return '%032x' % hash_val 135 + 136 + 137 + @total_ordering 138 + class Point: 139 + """Simple 2-dimensional point.""" 140 + def __init__(self, x, y): 141 + self.x = x 142 + self.y = y 143 + 144 + def __add__(self, other): 145 + return Point(self.x + other.x, self.y + other.y) 146 + 147 + def __sub__(self, other): 148 + return Point(self.x - other.x, self.y - other.y) 149 + 150 + def __mul__(self, n): 151 + return Point(self.x * n, self.y * n) 152 + 153 + def __div__(self, n): 154 + return Point(self.x / n, self.y / n) 155 + 156 + def __neg__(self): 157 + return Point(-self.x, -self.y) 158 + 159 + def __eq__(self, other): 160 + return self.x == other.x and self.y == other.y 161 + 162 + def __ne__(self, other): 163 + return not self == other 164 + 165 + def __lt__(self, other): 166 + return self.manhattan < other.manhattan 167 + 168 + def __str__(self): 169 + return "({}, {})".format(self.x, self.y) 170 + 171 + def __repr__(self): 172 + return "Point({}, {})".format(self.x, self.y) 173 + 174 + def __hash__(self): 175 + return hash(tuple((self.x, self.y))) 176 + 177 + @property 178 + def manhattan(self): 179 + return abs(self.x) + abs(self.y) 180 + 181 + @property 182 + def distance(self): 183 + return math.sqrt(self.x ** 2 + self.y ** 2) 184 + 185 + def neighbours_4(self): 186 + return [self + p for p in DIRS_4] 187 + 188 + def neighbours_8(self): 189 + return [self + p for p in DIRS_8] 190 + 191 + 192 + DIRS_4 = DIRS = [ 193 + Point(0, 1), # north 194 + Point(1, 0), # east 195 + Point(0, -1), # south 196 + Point(-1, 0), # west 197 + ] 198 + 199 + DIRS_8 = [ 200 + Point(0, 1), # N 201 + Point(1, 1), # NE 202 + Point(1, 0), # E 203 + Point(1, -1), # SE 204 + Point(0, -1), # S 205 + Point(-1, -1), # SW 206 + Point(-1, 0), # W 207 + Point(-1, 1), # NW 208 + ]