2022-12-09 - Rope Bridge
(original .ipynb)
Day 9 puzzle input is a sequence of move instructions - up/down/left/right + a distance - (mine is here). Part 1 involves taking a rope of length two units (well "knots" but w/e) and moving it around, noting how many unique positions the tail sits in. Part 2 is the same, but for a rope of length ten units/knots.
puzzle_input_str = open("./puzzle_input/day9.txt").read()
test_input_str = """R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2"""
moves = {
"U": (-1, 0),
"D": ( 1, 0),
"L": ( 0, -1),
"R": ( 0, 1)
}
def parse_lines(lines):
for line in lines:
direction, moves_str = line.split(" ")
yield direction, int(moves_str)
def move(pos, dr, dc):
r, c = pos
return (r+dr, c+dc)
def should_move_knot(hr, hc, tr, tc):
return abs(hr-tr) > 1 or abs(hc-tc) > 1
def tail_move(hr, hc, tr, tc):
if should_move_knot(hr, hc, tr, tc):
dr = hr - tr
dc = hc - tc
return (
0 if dr == 0 else dr//abs(dr),
0 if dc == 0 else dc//abs(dc)
)
return (0, 0)
def part_one(input_str, knot_count=2):
knots = [(0,0) for _ in range(knot_count)]
tail_visited = {(0,0)}
for direction, distance in parse_lines(input_str.splitlines()):
dr, dc = moves[direction]
while distance > 0:
next_knots = []
for i, knot in enumerate(knots):
if i == 0:
knot = move(knot, dr, dc)
else:
knot = move(knot, *tail_move(*next_knots[i-1], *knot))
if i+1 == knot_count:
tail_visited.add(knot)
next_knots.append(knot)
knots = next_knots
distance -= 1
return len(tail_visited)
assert 13 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 6339
test_input_str_2 = """R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20"""
def part_two(input_str):
return part_one(input_str, 10)
assert 36 == part_two(test_input_str_2)
print("part two:", part_two(puzzle_input_str))
part two: 2541