Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


2021-12-05 - Hydrothermal Venture

(original .ipynb)

Day 5 puzzle input is a list of co-ordinate pairs that represent lines (mine is here). Part 1 involves finding how many points the horizontal and vertical lines cross at least twice. Part 2 involves the same but including diagonal lines too.

from collections import defaultdict

puzzle_input_str = open("puzzle_input/day5.txt").read()

test_input_str = """0,9 -> 5,9
8,0 -> 0,8
9,4 -> 3,4
2,2 -> 2,1
7,0 -> 7,4
6,4 -> 2,0
0,9 -> 2,9
3,4 -> 1,4
0,0 -> 8,8
5,5 -> 8,2"""


def parse_coord(coord):
    x, y = coord.split(",")
    return int(x), int(y)


def parse_lines(input_str):
    for line in input_str.split("\n"):
        p1, p2 = line.split(" -> ")
        x1, y1 = parse_coord(p1)
        x2, y2 = parse_coord(p2)
        yield (x1, y1, x2, y2)

        
def is_diagonal(x1, y1, x2, y2):
    return not(x1 == x2 or y1 == y2)


def find_step(p1, p2):
    if p1 == p2:
        return 0
    return 1 if p2 > p1 else -1


def line_points(x1, y1, x2, y2):
    dx = find_step(x1, x2)
    dy = find_step(y1, y2)
    while not (x1 == x2 and y1 == y2):
        yield (x1, y1)
        x1 += dx
        y1 += dy
    yield (x1, y1)

        
def find_visited_points(lines):
    visited = defaultdict(lambda:0)
    for line in lines:
        for x, y in line_points(*line):
            visited[(x,y)] += 1
    return visited
    

def part_one(input_str):
    lines = parse_lines(input_str)
    visited = find_visited_points(line for line in lines if not is_diagonal(*line))
    return sum(1 for n in visited.values() if n >= 2)


assert 5 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 5197
def part_two(input_str):
    lines = parse_lines(input_str)
    visited = find_visited_points(lines)
    return sum(1 for n in visited.values() if n >= 2)


assert 12 == part_two(test_input_str)

print("part two:", part_two(puzzle_input_str))
part two: 18605