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

Completed 2023 Day 03

parent cc512ba5
No related branches found
No related tags found
No related merge requests found
from typing import List, Optional
from ImportData import import_data
day: int = 3
sample_data: List[str] = '''
467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..
'''.split('\n')[1:-1]
data_structure: type = List[str]
def parse_data(data: List[str]) -> data_structure:
# add some padding so that we won't have to look for borders later
padded_data: List[str] = []
for string in data:
padded_data.append(f' {string} ')
length = len(padded_data[0])
padded_data.append('.' * length)
padded_data.insert(0, '.' * length)
return padded_data
def is_part_number(data: data_structure, row: int, first_column: int, last_column: int) -> bool:
symbols = frozenset({'!', '@', '#', '$', '%', '^', '&', '*', '-', '+', '=', '/', '?'})
found_symbol: bool = False
for symbol in symbols:
if symbol in data[row - 1][first_column - 1:last_column + 1] \
or symbol in data[row][first_column - 1:last_column + 1] \
or symbol in data[row + 1][first_column - 1:last_column + 1]:
found_symbol = True
return found_symbol
def part1(data: data_structure) -> int:
number: Optional[int] = None
first_column: int = 0
last_column: int
part_numbers: List[int] = []
for row, string in enumerate(data):
for column, character in enumerate(string):
if character.isdigit():
if number is None:
number = int(character)
first_column = column
else:
number = 10 * number + int(character)
else:
if number is not None:
last_column = column
if is_part_number(data, row, first_column, last_column):
part_numbers.append(number)
number = None
return sum(part_numbers)
class Gear:
gears: List["Gear"] = []
def __init__(self, row: int, column: int):
self.row = row
self.column = column
self.numbers: List[int] = []
@classmethod
def add_number_to_gear(cls, number: int, row: int, column: int):
candidates = [gear for gear in Gear.gears if gear.row == row and gear.column == column]
gear: Gear
if candidates:
gear = candidates[0]
else:
gear = Gear(row, column)
Gear.gears.append(gear)
gear.numbers.append(number)
def look_for_gear(number: int, data: data_structure, row: int, first_column: int, last_column: int):
try:
column = data[row - 1].index('*', first_column - 1, last_column + 1)
Gear.add_number_to_gear(number, row - 1, column)
except ValueError:
pass
try:
column = data[row].index('*', first_column - 1, last_column + 1)
Gear.add_number_to_gear(number, row, column)
except ValueError:
pass
try:
column = data[row + 1].index('*', first_column - 1, last_column + 1)
Gear.add_number_to_gear(number, row + 1, column)
except ValueError:
pass
def part2(data: data_structure) -> int:
number: Optional[int] = None
first_column: int = 0
last_column: int
for row, string in enumerate(data):
for column, character in enumerate(string):
if character.isdigit():
if number is None:
number = int(character)
first_column = column
else:
number = 10 * number + int(character)
else:
if number is not None:
last_column = column
look_for_gear(number, data, row, first_column, last_column)
number = None
return sum([gear.numbers[0] * gear.numbers[1] for gear in Gear.gears if len(gear.numbers) == 2])
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