Advent of Code 2022 day 9
Took me ages to work out a bug with part two. My original solution for part one worked fine and my code passed for the part 2 examples. As is almost always the case, the bug seems obvious now I know what it was!
from unittest import TestCase
from utils import get_raw_input
class Rope:
def __init__(self, number_of_knots=1):
self.head = [0, 0]
self.knots = [[0, 0] for _ in range(number_of_knots)]
self.tail_visits = set()
def move_head(self, direction):
if direction == "U":
self.head[1] += 1
elif direction == "R":
self.head[0] += 1
elif direction == "D":
self.head[1] -= 1
elif direction == "L":
self.head[0] -= 1
self.move_knots()
def move_knots(self):
for i, knot in enumerate(self.knots):
if i == 0:
knot_to_follow = self.head
else:
knot_to_follow = self.knots[i - 1]
x_difference = knot_to_follow[0] - knot[0]
y_difference = knot_to_follow[1] - knot[1]
if x_difference > 1 or (x_difference == 1 and abs(y_difference) == 2):
knot[0] += 1
if x_difference < -1 or (x_difference == -1 and abs(y_difference) == 2):
knot[0] -= 1
if y_difference > 1 or (y_difference == 1 and abs(x_difference) == 2):
knot[1] += 1
if y_difference < -1 or (y_difference == -1 and abs(x_difference) == 2):
knot[1] -= 1
if i + 1 == len(self.knots):
self.tail_visits.add(tuple(knot))
@property
def number_of_tail_visits(self):
return len(self.tail_visits)
def run(rope, moves):
for move in moves:
direction, distance = move.split()
for i in range(int(distance)):
rope.move_head(direction)
return rope
def part_one(input):
rope = Rope()
run(rope, input)
return rope.number_of_tail_visits
def part_two(input):
rope = Rope(9)
run(rope, input)
return rope.number_of_tail_visits
if __name__ == "__main__":
input = get_raw_input("day_09_input.txt")
print(f"Part one: {part_one(input)}")
print(f"Part two: {part_two(input)}")
class TextExamples(TestCase):
def setUp(self):
self.first_example = [
"R 4",
"U 4",
"L 3",
"D 1",
"R 4",
"D 1",
"L 5",
"R 2",
]
self.second_example = [
"R 5",
"U 8",
"L 8",
"D 3",
"R 17",
"D 10",
"L 25",
"U 20",
]
def test_part_one_example(self):
self.assertEqual(part_one(self.first_example), 13)
def test_part_one_example_one(self):
self.assertEqual(part_two(self.first_example), 1)
def test_part_one_example_two(self):
self.assertEqual(
part_two(self.second_example),
36,
)