···11+import os # NOQA
22+import sys # NOQA
33+import re # NOQA
44+import math # NOQA
55+import fileinput
66+from string import ascii_uppercase, ascii_lowercase # NOQA
77+from collections import Counter, defaultdict, deque, namedtuple # NOQA
88+from itertools import count, product, permutations, combinations, combinations_with_replacement # NOQA
99+1010+from utils import parse_line, parse_nums, mul, all_unique, factors, memoize, primes # NOQA
1111+from utils import new_table, transposed, rotated # NOQA
1212+from utils import md5, sha256, knot_hash # NOQA
1313+from utils import VOWELS, CONSONANTS # NOQA
1414+from utils import Point, DIRS, DIRS_4, DIRS_8 # NOQA
1515+1616+# Itertools Functions:
1717+# product('ABCD', repeat=2) AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
1818+# permutations('ABCD', 2) AB AC AD BA BC BD CA CB CD DA DB DC
1919+# combinations('ABCD', 2) AB AC AD BC BD CD
2020+# combinations_with_replacement('ABCD', 2) AA AB AC AD BB BC BD CC CD DD
2121+2222+total = 0
2323+result = []
2424+table = new_table(None, width=2, height=4)
2525+2626+for i, line in enumerate(fileinput.input()):
2727+ line = line.strip()
2828+ nums = parse_nums(line)
2929+ data = parse_line(r'', line)
3030+3131+ if i == 0:
3232+ print(data)
+219
2019/utils.py
···11+import re
22+import math
33+import hashlib
44+import operator
55+from functools import total_ordering
66+77+88+LETTERS = [x for x in 'abcdefghijklmnopqrstuvwxyz']
99+VOWELS = {'a', 'e', 'i', 'o', 'u'}
1010+CONSONANTS = set(x for x in LETTERS if x not in VOWELS)
1111+1212+1313+def parse_line(regex, line):
1414+ ret = []
1515+ for match in re.match(regex, line).groups():
1616+ try:
1717+ ret.append(int(match))
1818+ except ValueError:
1919+ ret.append(match)
2020+2121+ return ret
2222+2323+2424+def parse_nums(line, negatives=True):
2525+ num_re = r'-?\d+' if negatives else r'\d+'
2626+ return [int(n) for n in re.findall(num_re, line)]
2727+2828+2929+def new_table(val, width, height):
3030+ return [[val for _ in range(width)] for _ in range(height)]
3131+3232+3333+def transposed(matrix):
3434+ """Returns the transpose of the given matrix."""
3535+ return [list(r) for r in zip(*matrix)]
3636+3737+3838+def rotated(matrix):
3939+ """Returns the given matrix rotated 90 degrees clockwise."""
4040+ return [list(r) for r in zip(*matrix[::-1])]
4141+4242+4343+def mul(lst):
4444+ """Like sum(), but for multiplication."""
4545+ return reduce(operator.mul, lst, 1) # NOQA
4646+4747+4848+def chunks(l, n):
4949+ """Yield successive n-sized chunks from l."""
5050+ for i in range(0, len(l), n):
5151+ yield l[i:i + n]
5252+5353+5454+def all_unique(lst):
5555+ return len(lst) == len(set(lst))
5656+5757+5858+def factors(n):
5959+ """Returns the factors of n."""
6060+ return sorted(
6161+ x for tup in (
6262+ [i, n // i] for i in range(1, int(n ** 0.5) + 1)
6363+ if n % i == 0)
6464+ for x in tup)
6565+6666+6767+def memoize(f):
6868+ """Simple dictionary-based memoization decorator"""
6969+ cache = {}
7070+7171+ def _mem_fn(*args):
7272+ if args not in cache:
7373+ cache[args] = f(*args)
7474+ return cache[args]
7575+7676+ _mem_fn.cache = cache
7777+ return _mem_fn
7878+7979+8080+def _eratosthenes(n):
8181+ """http://stackoverflow.com/a/3941967/239076"""
8282+ # Initialize list of primes
8383+ _primes = [True] * n
8484+8585+ # Set 0 and 1 to non-prime
8686+ _primes[0] = _primes[1] = False
8787+8888+ for i, is_prime in enumerate(_primes):
8989+ if is_prime:
9090+ yield i
9191+9292+ # Mark factors as non-prime
9393+ for j in xrange(i * i, n, i): # NOQA
9494+ _primes[j] = False
9595+9696+9797+def primes(n):
9898+ """Return a list of primes from [2, n)"""
9999+ return list(_eratosthenes(n))
100100+101101+102102+def md5(msg):
103103+ m = hashlib.md5()
104104+ m.update(msg)
105105+ return m.hexdigest()
106106+107107+108108+def sha256(msg):
109109+ s = hashlib.sha256()
110110+ s.update(msg)
111111+ return s.hexdigest()
112112+113113+114114+def knot_hash(msg):
115115+ lengths = [ord(x) for x in msg] + [17, 31, 73, 47, 23]
116116+ sparse = range(0, 256)
117117+ pos = 0
118118+ skip = 0
119119+120120+ for _ in range(64):
121121+ for l in lengths:
122122+ for i in range(l // 2):
123123+ x = (pos + i) % len(sparse)
124124+ y = (pos + l - i - 1) % len(sparse)
125125+ sparse[x], sparse[y] = sparse[y], sparse[x]
126126+127127+ pos = pos + l + skip % len(sparse)
128128+ skip += 1
129129+130130+ hash_val = 0
131131+132132+ for i in range(16):
133133+ res = 0
134134+ for j in range(0, 16):
135135+ res ^= sparse[(i * 16) + j]
136136+137137+ hash_val += res << ((16 - i - 1) * 8)
138138+139139+ return '%032x' % hash_val
140140+141141+142142+@total_ordering
143143+class Point:
144144+ """Simple 2-dimensional point."""
145145+ def __init__(self, x, y):
146146+ self.x = x
147147+ self.y = y
148148+149149+ def __add__(self, other):
150150+ return Point(self.x + other.x, self.y + other.y)
151151+152152+ def __sub__(self, other):
153153+ return Point(self.x - other.x, self.y - other.y)
154154+155155+ def __mul__(self, n):
156156+ return Point(self.x * n, self.y * n)
157157+158158+ def __div__(self, n):
159159+ return Point(self.x / n, self.y / n)
160160+161161+ def __neg__(self):
162162+ return Point(-self.x, -self.y)
163163+164164+ def __eq__(self, other):
165165+ return self.x == other.x and self.y == other.y
166166+167167+ def __ne__(self, other):
168168+ return not self == other
169169+170170+ def __lt__(self, other):
171171+ return self.manhattan < other.manhattan
172172+173173+ def __str__(self):
174174+ return "({}, {})".format(self.x, self.y)
175175+176176+ def __repr__(self):
177177+ return "Point({}, {})".format(self.x, self.y)
178178+179179+ def __hash__(self):
180180+ return hash(tuple((self.x, self.y)))
181181+182182+ def to(self, other):
183183+ return math.sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2)
184184+185185+ def to_manhattan(self, other):
186186+ return abs(self.x - other.x) + abs(self.y - other.y)
187187+188188+ @property
189189+ def manhattan(self):
190190+ return abs(self.x) + abs(self.y)
191191+192192+ @property
193193+ def distance(self):
194194+ return math.sqrt(self.x ** 2 + self.y ** 2)
195195+196196+ def neighbours_4(self):
197197+ return [self + p for p in DIRS_4]
198198+199199+ def neighbours_8(self):
200200+ return [self + p for p in DIRS_8]
201201+202202+203203+DIRS_4 = DIRS = [
204204+ Point(0, 1), # north
205205+ Point(1, 0), # east
206206+ Point(0, -1), # south
207207+ Point(-1, 0), # west
208208+]
209209+210210+DIRS_8 = [
211211+ Point(0, 1), # N
212212+ Point(1, 1), # NE
213213+ Point(1, 0), # E
214214+ Point(1, -1), # SE
215215+ Point(0, -1), # S
216216+ Point(-1, -1), # SW
217217+ Point(-1, 0), # W
218218+ Point(-1, 1), # NW
219219+]