Day 10 - Advent of Code 2023

Working solution for the day 10 puzzles.

Parts One and Two

""" day_10_01_02.py """

# usage: python3 day_10_01_02.py < input

import sys

ref = {('n', '|'): '|7FS', ('s', '|'): '|LJS', ('e', '-'): '-J7S',
       ('w', '-'): '-LFS', ('n', 'L'): '|7FS', ('e', 'L'): '-J7S',
       ('n', 'J'): '|7FS', ('w', 'J'): '-LFS', ('w', '7'): '-LFS',
       ('s', '7'): '|LJS', ('e', 'F'): '-J7S', ('s', 'F'): '|LJS',
       ('n', 'S'): '|7F', ('e', 'S'): '-J7', ('w', 'S'): '-LF',
       ('s', 'S'): '|LJ'}

s_ref = {('e', 'n'): 'F', ('e', 'e'): '-', ('n', 'n'): '|',
         ('n', 'w'): 'L', ('n', 'e'): 'J', ('w', 'n'): '7'}


def move(way, position):
    """ what's the next location if I go this way from position """
    deltas = {'n': (-1, 0), 'e': (0, 1), 'w': (0, -1), 's': (1, 0)}
    return position[0] + deltas[way][0], position[1] + deltas[way][1]


with sys.stdin as input_file:
    plan = input_file.read().split()

rows, cols = len(plan), len(plan[0])

for j, row in enumerate(plan):
    i = row.find('S')
    if i == -1:
        continue
    pos = j, i
    break

s_pipe = []
path = []
while True:
    path.append(pos)
    pipe = plan[pos[0]][pos[1]]
    for bearing in ['n', 'e', 'w', 's']:
        j, i = move(bearing, pos)
        if j < 0 or j == rows or i < 0 or i == cols:
            continue
        if (j, i) in path:
            if plan[j][i] == 'S' and 'S' in ref.get((bearing, pipe), ''):
                s_pipe.append(bearing)
            continue
        if plan[j][i] in ref.get((bearing, pipe), ''):
            pos = j, i
            if pipe == 'S':
                s_pipe.append(bearing)
            break
    else:
        break

print(len(path) // 2)

plan[path[0][0]] = plan[path[0][0]].replace('S', s_ref[tuple(s_pipe)])

plan2 = [list('.' * cols) for _ in range(rows)]
for j, i in path:
    plan2[j][i] = plan[j][i]

count = 0

for j, row in enumerate(plan2):
    for i, ground in enumerate(row[:-1]):
        if ground != '.':
            continue
        inside = False
        for tile in row[i + 1:]:
            if tile in ['.', '-']:
                continue
            if tile == '|':
                inside = not inside
            elif tile in ['F', 'L']:
                start = tile
            elif tile in ['J', '7']:
                if (start, tile) == ('F', 'J') or (start, tile) == ('L', '7'):
                    inside = not inside
        if inside:
            count += 1

print(count)