|
- import collections
- import hashlib
- import itertools
- import math
- import os
- import re
- import sys
- from pathlib import Path
-
- import requests
-
-
- def integers(line):
- return [int(n) for n in re.findall(r'\d+', line)]
-
-
- def lcm(a, b):
- return abs(a * b) // math.gcd(a, b)
-
-
- def render(grid, brush=None):
- if brush is None:
- brush = {v: v for v in grid.values()}
- if isinstance(brush, str):
- brush = {i: c for i, c in enumerate(brush)}
- xmin, *_, xmax = sorted(int(p.real) for p in grid)
- ymin, *_, ymax = sorted(int(p.imag) for p in grid)
- brush[None] = ' '
- rendered = ''
- for y in range(ymin, ymax + 1):
- for x in range(xmin, xmax + 1):
- rendered += brush[grid.get(complex(x, y))]
- rendered += '\n'
- return rendered
-
-
- def read_image(text):
- grid = collections.defaultdict(str)
- for y, line in enumerate(text.splitlines()):
- for x, cell in enumerate(line):
- grid[complex(x, y)] = cell
- return grid, x + 1, y + 1
-
-
- def shortest_path(start, end, move):
- seen = {}
- edge = {start: None}
- while edge:
- seen.update(edge)
- edge = {
- adj: pos
- for pos in edge
- for adj in move(pos)
- if adj not in seen
- }
- if end in seen:
- break
- else:
- raise RuntimeError('Path not found', seen)
- path = []
- while end:
- path.append(end)
- end = seen[end]
- return path[::-1]
-
-
- def get_dat():
- path = sys.argv[1]
- year, qn = map(int, re.findall(r'\d+', sys.argv[1]))
- url = f'https://adventofcode.com/{year}/day/{qn}/input'
- cookies = {'session': os.environ['SESSION']}
- response = requests.get(url, cookies=cookies)
- response.raise_for_status()
- Path(path).write_bytes(response.content)
-
-
- def batch(iterable, size):
- count = itertools.count()
- for _, sub in itertools.groupby(iterable, lambda _: next(count) // size):
- yield sub
-
-
- def md5(string):
- return hashlib.md5(string.encode()).hexdigest()
-
-
- def loop_consume(lines, handler):
- instructions = collections.deque(lines)
- count = 0
- while instructions:
- ok = handler(instructions[0])
- if ok:
- instructions.popleft()
- count = 0
- elif count < len(instructions):
- instructions.rotate(1)
- count += 1
- else:
- raise RuntimeError('Reached steady state')
|