# Advent of Code Day 3¶

In [1]:
with open("AoC/input3.txt") as input_file:

In [2]:
def segments(steps):
segments = []
current = (0, 0)
for step in steps:
if step[0] == 'R':
b = (current[0] + step[1], current[1])
elif step[0] == 'U':
b = (current[0], current[1] + step[1])
elif step[0] == 'L':
b = (current[0] - step[1], current[1])
elif step[0] == 'D':
b = (current[0], current[1] - step[1])
segments.append((current, b))
current = b
return segments

In [3]:
def intersect(segmentA, segmentB):
a1, a2 = segmentA
b1, b2 = segmentB

for ax0, ax1 in [(0, 1), (1, 0)]:
if a1[ax0] == a2[ax0] and b1[ax1] == b2[ax1] and \
min(a1[ax1], a2[ax1]) <= b1[ax1] and b1[ax1] <= max(a1[ax1], a2[ax1]) and \
min(b1[ax0], b2[ax0]) <= a1[ax0] and a1[ax0] <= max(b1[ax0], b2[ax0]):
return a1[ax0], b1[ax1]

# Doesn't handle overlaps
return None

In [4]:
def process(input_str):
parsed = [[(y[0], int(y[1:])) for y in x.split(",")] for x in input_str.strip().split("\n")]
lines = list(map(segments, parsed))

min_dist = None
for lineA in lines[0]:
for lineB in lines[1]:
pt = intersect(lineA, lineB)
dist = abs(pt[0]) + abs(pt[1]) if pt else None
if dist and (not min_dist or min_dist > dist):
min_dist = dist

return min_dist

In [5]:
process(test_input)

Out[5]:
221
In [6]:
process("""R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83""")

Out[6]:
159
In [7]:
def length(line):
return abs(line[0][0] - line[1][0]) + abs(line[0][1] - line[1][1])

In [8]:
def process2(input_str):
parsed = [[(y[0], int(y[1:])) for y in x.split(",")] for x in input_str.strip().split("\n")]
lines = list(map(segments, parsed))

min_steps = None
stepsA = 0
for lineA in lines[0]:

stepsB = 0
for lineB in lines[1]:
pt = intersect(lineA, lineB)
steps = stepsA + stepsB + length((lineA[0], pt)) + length((lineB[0], pt)) if pt else None
if steps and (not min_steps or min_steps > steps) and not (pt[0] == 0 and pt[1] == 0):
print(pt, steps, lineA, lineB)
min_steps = steps

stepsB += length(lineB)

stepsA += length(lineA)

return min_steps

In [9]:
process2("""R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83""")

(158, -12) 610 ((158, -30), (158, 53)) ((155, -12), (238, -12))

Out[9]:
610
In [10]:
process2(test_input)

(998, 349) 39290 ((998, 0), (998, 367)) ((584, 349), (1238, 349))
(367, 1211) 25888 ((998, 367), (1733, 367)) ((1211, 823), (1211, -117))
(1733, 823) 23850 ((1733, 367), (1733, 1293)) ((2184, 823), (1211, 823))
(1756, 1665) 18542 ((1756, 1293), (1756, 1750)) ((1330, 1665), (1968, 1665))

Out[10]:
18542

I started this one early in the morning and not at midnight, but timed myself just to see how I perform. I ended up taking 50 minutes, which is pretty slow because of several easy mistakes. Notes to self:

• Remember to structure the code to allow easily testing sample inputs.
• Actually remember to test sample inputs.
• It might be more valuable to edit the solution in place for the second star instead of starting from scratch.
• Keep my notebook ready to paste strings of test inputs easily

Looking at the winning solutions from the subreddit, I ended up wasting too much time doing intersections instead of simply brute forcing a solution by assembling a collection of grid points -- which is a good trick to remember for grid/integer based problems.

TODO: Try drawing graphs of wires someday.