advent of code 2023 edition
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.
 
 
 
 
 
 
aoc_2023/aoc_03.py

138 lines
3.2 KiB

#!python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("filename", help="the file from which to take the list of games")
args = parser.parse_args()
parts = []
notparts = []
gearsum = 0
def check_neighbors(nbrs):
for n in nbrs:
if n not in ".0123456789\n":
return True
def neighbors(x, y, ls):
out = []
for dx in range(-1,2):
for dy in range(-1,2):
if dx == 0 and dy == 0:
continue
if y+dy < 0 or y+dy >= len(ls):
continue
if x+dx < 0 or x+dx >= len(ls[y+dy]):
continue
out.append(ls[y+dy][x+dx])
return out
def numerical_neighbors(x, y, ls):
out = set()
for dx in range(-1, 2):
for dy in range(-1, 2):
if dx == 0 and dy == 0:
continue
if y+dy < 0 or y+dy >= len(ls):
continue
if x+dx < 0 or x+dx >= len(ls[y+dy]):
continue
if ls[y+dy][x+dx] in "0123456789":
out |= {(x+dx,y+dy, ls[y+dy][x+dx])}
return out
def get_number(x,y, lines):
"""assumes (x,y) is the coordinates of a digit in lines"""
while x-1 >= 0 and lines[y][x-1] in "0123456789":
x = x-1
start = (x,y)
number = ""
coords = set()
while lines[y][x] in "0123456789":
number += lines[y][x]
coords |= {(x,y)}
x += 1
if x >= len(lines[y]): break
return (number, frozenset(coords))
with open(args.filename, "r") as file:
lines = file.readlines()
for y, l in enumerate(lines):
number = ""
nbrs = []
for x, c in enumerate(l):
if c == "\n": print("HEYYYY")
if c in "0123456789":
number = number + c
nbrs.extend(neighbors(x,y,lines))
if c not in "0123456789\n" and number != "":
if check_neighbors(nbrs):
#print("found a number:", number, "".join(nbrs), " and accepted it")
parts.append(int(number))
else:
#print("found a number:", number, "".join(nbrs), " and rejected it")
notparts.append(int(number))
number = ""
nbrs = []
if c not in "0123456789":
continue
if number != "":
if check_neighbors(nbrs):
print("found a number:", number, "".join(nbrs), " and accepted it")
parts.append(int(number))
else:
print("found a number:", number, "".join(nbrs), " and rejected it")
notparts.append(int(number))
number = ""
nbrs = []
gearsum = 0
for y, l in enumerate(lines):
for x, c in enumerate(l):
if c == "*":
print("found a gear at ", x, " ", y)
gear_nums = []
gear_coordsets = set()
# we found a gear
neighbors = numerical_neighbors(x,y,lines)
print("the gear had neighbors ", neighbors)
for xa, ya, neighboring_number in neighbors:
number, coords = get_number(xa, ya, lines)
print("found a neighbor ", number, " at coords ", coords)
if coords in gear_coordsets:
print("rejecting that neighbor because we already got it")
# we've already got this number. mvoe alnog
continue
else:
print("adding it to gear cordsets", gear_coordsets)
gear_nums.append(number)
gear_coordsets |= {coords}
print("which corresponded to numbers", gear_nums)
if len(gear_nums) == 2:
gearsum += int(gear_nums[0])*int(gear_nums[1])
print("accepted:")
print(parts)
print("rejected:")
print(notparts)
print("sum of parts are:", sum(parts))
print("sum of unique parts are: ", sum(set(parts)))
print("gear sum is: ", gearsum)