Select Git revision
-
Duncan Holmes authored
it's very minor. only has 2/3rds of 1st "ger reflexive" function may god help me and all of the students of UNL avoid the evil that lurks here
Duncan Holmes authoredit's very minor. only has 2/3rds of 1st "ger reflexive" function may god help me and all of the students of UNL avoid the evil that lurks here
Day10.py 6.91 KiB
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)))