You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.1 KiB
99 lines
3.1 KiB
lines = open('inputs/day3.txt').readlines()
|
|
xlen = len(lines)
|
|
ylen = len(lines[0])
|
|
|
|
def symbol_positions(lines: list[str]) -> list[tuple]:
|
|
positions = []
|
|
symbols = []
|
|
for idx, line in enumerate(lines):
|
|
for idy, c in enumerate(line.strip('\n')):
|
|
if not c.isdigit() and c != ".":
|
|
positions.append((idx, idy))
|
|
symbols.append(c)
|
|
return positions, symbols
|
|
|
|
def find_first_digit(lines: list[str], coords: tuple) -> tuple:
|
|
x, y = coords
|
|
if y == 0:
|
|
return coords
|
|
elif not lines[x][y-1].isdigit():
|
|
return coords
|
|
else:
|
|
return find_first_digit(lines, (x, y-1))
|
|
|
|
def full_number(lines: list[str], coords: tuple) -> int:
|
|
x, y = coords
|
|
nr = lines[x][y]
|
|
counter = 1
|
|
while (y + counter) < (ylen - 1):
|
|
if lines[x][y + counter].isdigit():
|
|
nr += lines[x][y + counter]
|
|
counter += 1
|
|
else:
|
|
break
|
|
return int(nr)
|
|
|
|
def adjacent_numbers(lines: list[str], xy: tuple) -> tuple:
|
|
# returns bool and coords of first digit in number
|
|
coords = []
|
|
x, y = xy
|
|
neighbours_exist = False
|
|
if x > 0:
|
|
if lines[x-1][y].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x-1, y)))
|
|
if y > 0:
|
|
if lines[x-1][y-1].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x-1, y-1)))
|
|
if y < (ylen - 1):
|
|
if lines[x-1][y+1].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x-1, y+1)))
|
|
if x < (xlen - 1):
|
|
if lines[x+1][y].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x+1, y)))
|
|
if y > 0:
|
|
if lines[x+1][y-1].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x+1, y-1)))
|
|
if y < (ylen - 1):
|
|
if lines[x+1][y+1].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x+1, y+1)))
|
|
if y > 0:
|
|
if lines[x][y-1].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x, y-1)))
|
|
if y < (ylen - 1):
|
|
if lines[x][y+1].isdigit():
|
|
neighbours_exist = True
|
|
coords.append(find_first_digit(lines, (x, y+1)))
|
|
return neighbours_exist, set(coords)
|
|
|
|
positions, symbols = symbol_positions(lines)
|
|
numbers_pos = []
|
|
for s in positions:
|
|
has_neighbour, coords = adjacent_numbers(lines, s)
|
|
if has_neighbour:
|
|
numbers_pos.append(coords)
|
|
|
|
number_coords = set([x for y in numbers_pos for x in y])
|
|
numbers = []
|
|
for nr in number_coords:
|
|
numbers.append(full_number(lines, nr))
|
|
|
|
print(f'Solution Part 1: {sum(numbers)}')
|
|
|
|
gear_ratios = []
|
|
for p, c in zip(positions, symbols):
|
|
if c == "*":
|
|
has_neighbour, coords = adjacent_numbers(lines, p)
|
|
coords = list(coords)
|
|
if len(coords) == 2:
|
|
gear_ratios.append(full_number(lines, coords[0]) * full_number(lines, coords[1]))
|
|
|
|
print(f"Solution Part 2: {sum(gear_ratios)}")
|
|
|