advent-of-code/2023/python/day03.py
2023-12-03 16:29:10 -05:00

95 lines
2.5 KiB
Python

import matrix
import shared
import itertools
import functools
from pprint import pprint
from collections import defaultdict
SYMBOLS="*%@#+-/$=&"
def get_all_numbers_and_starting_coords(mat):
"""
for a coordinate, walks right until it encounters a non digit,
when it does, it adds that number string to a collection,
and starts over, walking right until it continues to next row
"""
nums = []
for y, row in enumerate(mat):
x = 0
while x < len(row):
num = matrix.number_starting_at(mat, x,y)
if num is None:
x += 1
continue
nums.append(((x,y), num))
x += len(num)
return nums
def get_row_coords(x1, y, length):
"""
for a given x,y point, it just creates the rest of the x/y coords to the right of this coord for a run
"""
coords = []
for x in range(x1, x1+length):
coords.append((x,y))
return coords
def process_number(mx, coords, num):
line_coords = get_row_coords(*coords, len(num))
for coord in line_coords:
any_symbols = [(cs, v) for cs,v in matrix.get_neighbor_coords(mx, *coord) if v in SYMBOLS]
if any_symbols:
return True, any_symbols[0]
return False, None
# @shared.profile
def part1(mat):
choose = []
nums = get_all_numbers_and_starting_coords(mat)
for coords, num in nums:
valid, symbol_coord = process_number(mat, coords, num)
if valid:
choose.append(num)
total = 0
for n in choose:
total += int(n)
print(total)
# @shared.profile
def part2(mat):
splats = matrix.find_in_matrix(mat, "*", False)
_nums = get_all_numbers_and_starting_coords(mat)
symbols = defaultdict(list)
nums = get_all_numbers_and_starting_coords(mat)
for coords, num in nums:
valid, sc = process_number(mat, coords, num)
if valid:
symbols[(sc[0]['r'],sc[0]['c'])].append(num)
total = 0
for splat in splats:
neighbors = symbols[splat]
if len(neighbors) != 2:
continue
ratio = int(neighbors[0]) * int(neighbors[1])
total += ratio
print(total)
def main():
mat = shared.load_file_char_matrix(shared.get_fname(3))
with shared.elapsed_timer() as elapsed:
part1(mat)
print("🕒", elapsed())
with shared.elapsed_timer() as elapsed:
part2(mat)
print("🕒", elapsed())
if __name__ == "__main__":
main()