| @@ -0,0 +1,4 @@ | |||
| *.dat | |||
| __pycache__/ | |||
| .DS_Store | |||
| venv/ | |||
| @@ -0,0 +1,13 @@ | |||
| FILE = $(shell find . -name p??.py -type f | xargs ls -rt | tail -n 1) | |||
| DATA = $(shell echo $(FILE) | sed -e s/\.py/\.dat/) | |||
| PYTHONPATH=. | |||
| main: venv/ | |||
| @touch $(DATA) | |||
| @cat $(DATA) | venv/bin/python -u $(FILE) | |||
| venv/: requirements.txt | |||
| rm -rf venv/ | |||
| python3 -m venv venv | |||
| venv/bin/pip install -r requirements.txt | |||
| touch requirements.txt venv/ | |||
| @@ -0,0 +1,4 @@ | |||
| pypng | |||
| numpy | |||
| scipy | |||
| scikit-image | |||
| @@ -0,0 +1,68 @@ | |||
| import collections | |||
| import re | |||
| from pathlib import Path | |||
| def read_in(): | |||
| grid = collections.defaultdict(lambda: ' ') | |||
| for _ in Path('y2018/p17.dat').read_text().splitlines(): | |||
| _ = _.replace(',', ';') | |||
| _ = re.sub(r'(\d+)\.\.(\d+)', r'range(\1, \2 + 1)', _) | |||
| _ = re.sub(r'=(\d+)', r'=[\1]', _) | |||
| exec(_, globals()) | |||
| grid.update({(X, Y): '#' for X in x for Y in y}) | |||
| return grid | |||
| def write_out(grid, path): | |||
| text = '\n'.join( | |||
| ''.join(grid[x, y] for x in range(xmin - 5, xmax + 5)) | |||
| for y in range(ymin, ymax + 1) | |||
| ) | |||
| Path(path).write_text(text) | |||
| def flow(start): | |||
| stack = [start] | |||
| while stack: | |||
| x, y = stack.pop() | |||
| grid[x, y] = '~' | |||
| if y > ymax: | |||
| break | |||
| for dx, dy in [(1, 0), (-1, 0), (0, 1)]: | |||
| new = x + dx, y + dy | |||
| if dy == 1 and grid[new] == '|': | |||
| stack.clear() | |||
| break | |||
| if grid[new] == ' ': | |||
| stack.append(new) | |||
| drain((x, y)) | |||
| def drain(end): | |||
| stack = [end] | |||
| while stack: | |||
| x, y = stack.pop() | |||
| grid[x, y] = '|' | |||
| if grid[x - 1, y] == '|' and grid[x + 1, y] == ' ' and grid[x, y + 1] != '|': | |||
| flow((x + 1, y)) | |||
| for dx, dy in [(-1, 0), (1, 0), (0, -1)]: | |||
| new = x + dx, y + dy | |||
| if grid[new] == '~': | |||
| stack.append(new) | |||
| grid = read_in() | |||
| xmin, *_, xmax = sorted(x for x, y in grid) | |||
| ymin, *_, ymax = sorted(y for x, y in grid) | |||
| flow((500, 0)) | |||
| counter = collections.Counter(grid.values()) | |||
| print(counter['~'] + counter['|']) | |||
| print(counter['~']) | |||
| write_out(grid, 'y2018/p17out.dat') | |||
| @@ -0,0 +1,74 @@ | |||
| import re | |||
| def parse(string): | |||
| return [int(n) for n in re.findall(r'-?\d+', string)] | |||
| def get_parameters(ns, pos, modes, N, writes): | |||
| for c in writes: | |||
| # paradox: return immediate mode to use positionally outside | |||
| modes[ord(c) - ord('a')] = '1' | |||
| for mode, x in zip(modes, ns[pos:][:N]): | |||
| yield { | |||
| '0': lambda: ns[x], | |||
| '1': lambda: x, | |||
| }[mode]() | |||
| yield pos + N | |||
| def compute(ns, inp): | |||
| if isinstance(ns, str): | |||
| ns = parse(ns) | |||
| pos = 0 | |||
| consume = lambda n, writes='': get_parameters(ns, pos, modes, n, writes) | |||
| while True: | |||
| op = ns[pos] % 100 | |||
| # instructions stupidly say ABC referring to parameters 3, 2, 1 | |||
| # we do a, b, c | |||
| modes = list(str(ns[pos] // 100).zfill(3)[::-1]) | |||
| pos += 1 | |||
| if op == 1: | |||
| a, b, c, pos = consume(3, 'c') | |||
| ns[c] = a + b | |||
| elif op == 2: | |||
| a, b, c, pos = consume(3, 'c') | |||
| ns[c] = a * b | |||
| elif op == 3: | |||
| a, pos = consume(1, 'a') | |||
| ns[a] = inp | |||
| elif op == 4: | |||
| a, pos = consume(1) | |||
| yield a | |||
| elif op == 5: | |||
| a, b, pos = consume(2) | |||
| if a != 0: | |||
| pos = b | |||
| elif op == 6: | |||
| a, b, pos = consume(2) | |||
| if a == 0: | |||
| pos = b | |||
| elif op == 7: | |||
| a, b, c, pos = consume(3, 'c') | |||
| ns[c] = int(a < b) | |||
| elif op == 8: | |||
| a, b, c, pos = consume(3, 'c') | |||
| ns[c] = int(a == b) | |||
| elif op == 99: | |||
| return | |||
| else: | |||
| raise RuntimeError(op) | |||
| @@ -0,0 +1,15 @@ | |||
| import sys | |||
| text = sys.stdin.read() | |||
| ns = [int(s) for s in text.splitlines()] | |||
| def handle(n): | |||
| m = n // 3 - 2 | |||
| return [m] + handle(m) if m > 0 else [] | |||
| if __name__ == '__main__': | |||
| print(sum(handle(n)[0] for n in ns)) | |||
| print(sum(sum(handle(n)) for n in ns)) | |||
| @@ -0,0 +1,18 @@ | |||
| import itertools | |||
| import re | |||
| import sys | |||
| from intcode import compute, parse | |||
| def check(noun, verb): | |||
| ns = parse(text) | |||
| ns[1:3] = [noun, verb] | |||
| list(compute(ns, 2)) | |||
| return ns[0] | |||
| text = sys.stdin.read() | |||
| print(check(12, 2)) | |||
| for noun, verb in itertools.product(range(100), repeat=2): | |||
| if check(noun, verb) == 19690720: | |||
| print(100 * noun + verb) | |||
| @@ -0,0 +1,24 @@ | |||
| import sys | |||
| text = sys.stdin.read() | |||
| maps = {'R': -1, 'D': -1j, 'L': 1, 'U': 1j} | |||
| info = [] | |||
| for path in text.splitlines(): | |||
| i, p = 0, 0 | |||
| best = {} | |||
| for a, *n in path.split(','): | |||
| d = maps[a] | |||
| for _ in range(int(''.join(n))): | |||
| i += 1 | |||
| p += d | |||
| if p not in best: | |||
| best[p] = i | |||
| info.append(best) | |||
| isect = set(info[0]) & set(info[1]) | |||
| print(int(min((abs(p.real) + abs(p.imag), p) for p in isect)[0])) | |||
| print(min(info[0][p] + info[1][p] for p in isect)) | |||
| @@ -0,0 +1,6 @@ | |||
| import sys | |||
| import itertools | |||
| strings = [str(n) for n in range(347312, 805915 + 1)] | |||
| print(sum(list(s) == sorted(s) and any(len(list(vs)) >= 2 for k, vs in itertools.groupby(s)) for s in strings)) | |||
| print(sum(list(s) == sorted(s) and any(len(list(vs)) == 2 for k, vs in itertools.groupby(s)) for s in strings)) | |||
| @@ -0,0 +1,27 @@ | |||
| import sys | |||
| from intcode import compute, parse | |||
| tests = [ | |||
| ('3,0,4,0,99', [(12421, 12421)]), | |||
| ('3,9,8,9,10,9,4,9,99,-1,8', [(8, 1), (7, 0)]), | |||
| ('3,9,7,9,10,9,4,9,99,-1,8', [(7, 1), (8, 0), (9, 0)]), | |||
| ('3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9', [(0, 0), (213, 1)]), | |||
| ('3,3,1105,-1,9,1101,0,0,12,4,12,99,1', [(0, 0), (213, 1)]), | |||
| (''' | |||
| 3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31, | |||
| 1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104, | |||
| 999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99 | |||
| ''', [(7, 999), (8, 1000), (9, 1001)]), | |||
| ] | |||
| for program, pairs in tests: | |||
| for inp, expect in pairs: | |||
| out = list(compute(program, inp))[-1] | |||
| assert out == expect, (out, expect) | |||
| text = sys.stdin.read() | |||
| print(list(compute(text, 1))[-1]) | |||
| print(list(compute(text, 5))[-1]) | |||