*.dat | |||||
__pycache__/ | |||||
.DS_Store | |||||
venv/ |
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/ |
pypng | |||||
numpy | |||||
scipy | |||||
scikit-image |
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') |
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) |
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)) |
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) |
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)) |
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)) |
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]) |