Skip to content
Snippets Groups Projects
Verified Commit 2f1fdcf1 authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Completed 2023 Day 10

parent 1ba0b5b1
No related branches found
No related tags found
No related merge requests found
import functools
from typing import List, Tuple
from ImportData import import_data
day: int = 10
# sample_data: List[str] = '''
# .....
# .S-7.
# .|.|.
# .L-J.
# .....
# '''.split('\n')[1:-1]
# sample_data: List[str] = '''
# 7-F7-
# .FJ|7
# SJLL7
# |F--J
# LJ.LJ
# '''.split('\n')[1:-1]
# sample_data: List[str] = '''
# ...........
# .S-------7.
# .|F-----7|.
# .||.....||.
# .||.....||.
# .|L-7.F-J|.
# .|..|.|..|.
# .L--J.L--J.
# ...........
# '''.split('\n')[1:-1]
# sample_data: List[str] = '''
# ..........
# .S------7.
# .|F----7|.
# .||....||.
# .||....||.
# .|L-7F-J|.
# .|..||..|.
# .L--JL--J.
# ..........
# '''.split('\n')[1:-1]
# sample_data: List[str] = '''
# .F----7F7F7F7F-7....
# .|F--7||||||||FJ....
# .||.FJ||||||||L7....
# FJL7L7LJLJ||LJ.L-7..
# L--J.L7...LJS7F-7L7.
# ....F-J..F7FJ|L7L7L7
# ....L7.F7||L7|.L7L7|
# .....|FJLJ|FJ|F7|.LJ
# ....FJL-7.||.||||...
# ....L---J.LJ.LJLJ...
# '''.split('\n')[1:-1]
sample_data: List[str] = '''
FF7FSF7F7F7F7F7F---7
L|LJ||||||||||||F--J
FL-7LJLJ||||||LJL-77
F--JF--7||LJLJ7F7FJ-
L---JF-JLJ.||-FJLJJ7
|F|F-JF---7F7-L7L|7|
|FFJF7L7F-JF7|JL---7
7-L-JL7||F7|L7F-7F7|
L.L7LFJ|||||FJL7||LJ
L7JLJL-JLJLJL--JLJ.L
'''.split('\n')[1:-1]
data_structure: type = Tuple[int, int, str, List[str]]
def parse_data(data: List[str]) -> data_structure:
initial_row: int = -1
initial_column: int = -1
initial_pipe: str
number_of_rows = len(data)
number_of_columns = len(data[0])
for row in range(number_of_rows):
for column in range(number_of_columns):
if data[row][column] == 'S':
initial_row = row
initial_column = column
initial_pipe = input('What is the shape of the initial pipe? ')
return initial_row, initial_column, initial_pipe, data
def part1(data: data_structure) -> int:
row, column, pipe, pipes = data
previous_locations: List[Tuple[int, int]] = [(row, column), (row, column)]
current_locations: List[Tuple[int, int]]
match pipe:
case '|':
current_locations = [(row + 1, column), (row - 1, column)]
case '-':
current_locations = [(row, column + 1), (row, column - 1)]
case 'L':
current_locations = [(row, column + 1), (row - 1, column)]
case 'J':
current_locations = [(row, column - 1), (row - 1, column)]
case '7':
current_locations = [(row, column - 1), (row + 1, column)]
case 'F':
current_locations = [(row, column + 1), (row + 1, column)]
case _:
raise ValueError(f'{pipe} at ({row},{column})')
distance: int = 1
while current_locations[0] != current_locations[1]:
distance += 1
for i in range(len(current_locations)):
previous_row, previous_column = previous_locations[i]
row, column = current_locations[i]
pipe = pipes[row][column]
previous_locations[i] = current_locations[i]
row_change = row - previous_row
column_change = column - previous_column
match pipe:
case '|' | '-':
current_locations[i] = (row + row_change, column + column_change)
case 'L' | '7':
current_locations[i] = (row + column_change, column + row_change)
case 'J' | 'F':
current_locations[i] = (row - column_change, column - row_change)
case _:
raise ValueError(f'{pipe} at ({row}, {column})')
return distance
def part2(data: data_structure) -> int:
row, column, pipe, pipes = data
# an extra copy of the pipes data, "zoomed in" to allow for gaps between pipes
tiles: [List[List[str]]] = [['I'] * (2 * len(pipes[0])) for _ in range(2 * len(pipes))]
# first, draw the main loop on the tiles copy
previous_location: Tuple[int, int] = (row, column)
current_location: Tuple[int, int]
match pipe:
case '|' | 'F':
current_location = (row + 1, column)
tiles[2 * row + 1][2 * column] = 'X'
case '-' | 'L':
current_location = (row, column + 1)
tiles[2 * row][2 * column + 1] = 'X'
case 'J' | '7':
current_location = (row, column - 1)
tiles[2 * row][2 * column - 1] = 'X'
case _:
raise ValueError(f'{pipe} at ({row},{column})')
previous_row, previous_column = previous_location
row, column = current_location
while tiles[2 * row][2 * column] != 'X':
tiles[2 * row][2 * column] = 'X'
pipe = pipes[row][column]
previous_location = current_location
row_change = row - previous_row
column_change = column - previous_column
match pipe:
case '|' | '-':
current_location = (row + row_change, column + column_change)
tiles[2 * row + row_change][2 * column + column_change] = 'X'
case 'L' | '7':
current_location = (row + column_change, column + row_change)
tiles[2 * row + column_change][2 * column + row_change] = 'X'
case 'J' | 'F':
current_location = (row - column_change, column - row_change)
tiles[2 * row - column_change][2 * column - row_change] = 'X'
case 'S':
pass
case _:
raise ValueError(f'{pipe} at ({row}, {column})')
previous_row, previous_column = previous_location
row, column = current_location
# now let's create a border
tiles = [['O'] * (2 * len(pipes[0]))] + tiles + [['O'] * (2 * len(tiles[0]))]
tiles = [['O'] + tile + ['O'] for tile in tiles]
# fill in the "outside"
finished: bool = False
while not finished:
finished = True
for row in range(1, len(tiles) - 1):
for column in range(1, len(tiles[0]) - 1):
if tiles[row][column] == 'I' and (tiles[row - 1][column] == 'O' or tiles[row][column - 1] == 'O' or
tiles[row + 1][column] == 'O' or tiles[row][column + 1] == 'O'):
tiles[row][column] = 'O'
finished = False
# now shrink it back down to size, step 1: remove the border
# arguably, this step is unnecessary, but it simplifies the expression in step 2
tiles = [row[1:-1] for row in tiles[1:-1]]
# shrink it back down to size, step 2: remove the "in between" tiles
new_tiles: List[List[str]] = []
for row in range(0, len(tiles), 2):
new_row: List[str] = []
for column in range(0, len(tiles[0]), 2):
new_row.append(tiles[row][column])
new_tiles.append(new_row)
# count the "inside"
return sum([functools.reduce(lambda x, y: x + y, map(lambda x: 1 if x == 'I' else 0, row)) for row in new_tiles])
if __name__ == '__main__':
production_ready = True
raw_data = import_data(day) if production_ready else sample_data
print(part1(parse_data(raw_data)))
print(part2(parse_data(raw_data)))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment