In [1]:

```
with open("AoC/input3.txt") as input_file:
test_input = input_file.read()
```

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]:

In [6]:

```
process("""R75,D30,R83,U83,L12,D49,R71,U7,L72
U62,R66,U55,R34,D71,R55,D58,R83""")
```

Out[6]:

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""")
```

Out[9]:

In [10]:

```
process2(test_input)
```

Out[10]:

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.