advent-of-code-2019/day03.py

83 lines
1.9 KiB
Python

#!/usr/bin/env python3
up = lambda v: (v[0], v[1] + 1)
down = lambda v: (v[0], v[1] - 1)
left = lambda v: (v[0] - 1, v[1])
right = lambda v: (v[0] + 1, v[1])
moves = {'U' : up,
'D' : down,
'L' : left,
'R' : right
}
def memoize(f):
cache = dict()
def memf(path):
if path not in cache:
cache[path] = f(path)
return cache[path]
return memf
def iterate(f, x, N):
for i in range(N):
yield x
x = f(x)
@memoize
def lines(path):
pos = (0, 0)
r = []
for move in path.split(','):
dir, steps = move[0], int(move[1:])
line = list(iterate(moves[dir], pos, steps+1))
r.append(line)
pos = line[-1]
return r
def coordinates(path, corners=True):
return sum((line[1:len(line) - 1 + corners]
for line in lines(path)), [])
def crossings(*paths):
return set.intersection(*(set(coordinates(path, corners=False))
for path in paths))
def min_crossing(path1, path2, f):
return min(f(v) for v in crossings(path1, path2))
def preproc(puzzle_input):
return puzzle_input.split()
def partI(paths):
key = lambda v: abs(v[0]) + abs(v[1])
path1, path2 = paths
return min_crossing(path1, path2, key)
def partII(paths):
path1, path2 = paths
def key(c1, c2):
r = lambda v: c1.index(v) + c2.index(v) + 2
return r
def min_steps(p1, p2):
c1, c2 = coordinates(p1), coordinates(p2)
return min_crossing(p1, p2, key(c1, c2))
return min_steps(path1, path2)
from main import Tests
tests = Tests()
tests.add("R75,D30,R83,U83,L12,D49,R71,U7,L72\n" +
"U62,R66,U55,R34,D71,R55,D58,R83",
partI=159,
partII=610)
tests.add("R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51\n" +
"U98,R91,D20,R16,D67,R40,U7,R15,U6,R7",
partI=135,
partII=410)