AdventOfCode2023/day3-2.py
2023-12-03 03:57:45 -06:00

390 lines
14 KiB
Python

import time
valid_symbols = "#$%&*+-/=@"#"/,!@#$%^&*()_-+={}[]"
w,h = (140,140)
with open("input_day3.txt") as file:
lines = [line.rstrip() for line in file]
matrix = [[0 for x in range(w)] for y in range(h)]
for y in range(h):
for x in range(w):
matrix[y][x] = lines[y][x]
class number:
def __init__(self,x,y,length=1,num=0):
self.x = x
self.y = y
self.length = length
self.number = num
def append(self,num=0):
self.length+=1
self.number = int( f"{self.number}{num}" )
def is_valid(num:number) -> bool:
#but first check if number is valid
result = False
for offset in range(num.length):
x = num.x+offset
y = num.y
check_upperleft = True
check_upper = True
check_upperright = True
check_midleft = True
check_midright = True
check_lowerleft = True
check_lower = True
check_lowerright = True
#if on first y dont check above
if num.y == 0:
check_upperleft,check_upper,check_upperright = (False,False,False)
#if on last y dont check below
if num.y == h-1:
check_lowerleft,check_lower,check_lowerright = (False,False,False)
# if on left or right horizontal edge
if x == 0:
check_midleft = False
if x >= w-1:
check_midright = False
check_upperright = False
check_lowerright = False
#now do comparison
if check_upperleft:
if is_symbol(str(matrix[y-1][x-1])):
return True
if check_upper:
if is_symbol(str(matrix[y-1][x])):
return True
if check_upperright:
if is_symbol(str(matrix[y-1][x+1])):
return True
if check_midleft:
if is_symbol(str(matrix[y][x-1])):
return True
if check_midright:
if is_symbol(str(matrix[y][x+1])):
return True
if check_lowerleft:
if is_symbol(str(matrix[y+1][x-1])):
return True
if check_lower:
if is_symbol(str(matrix[y+1][x])):
return True
if check_lowerright:
if is_symbol(str(matrix[y+1][x+1])):
return True
return False
def is_symbol(c):
if c in valid_symbols:
return True
return False
numbers = []
#140x140 matrix
y=-1
#look at every element in matrix for a number
for line in lines:
#start new line
y+=1
is_on_number = False
for x in range(w):
c = line[x]
if c.isnumeric():
if not is_on_number:
#start a new number record
is_on_number = True
new_num = number(x,y,num=int(c))
elif x == w-1:
new_num.append(c)
if is_valid(new_num):
numbers.append(new_num)
print(new_num.number)
is_on_number = False
else:
#append to existing number
new_num.append(c)
else:
#not a number anymore so finish the number and add to num list if number is valid
if is_on_number:
if is_valid(new_num):
numbers.append(new_num)
#print(new_num.number)
#time.sleep(0.1)
is_on_number = False
def check_gear_ratio(x,y):
check_upperleft = True
check_upper = True
check_upperright = True
check_midleft = True
check_midright = True
check_lowerleft = True
check_lower = True
check_lowerright = True
#if on first y dont check above
if y == 0:
check_upperleft,check_upper,check_upperright = (False,False,False)
#if on last y dont check below
if y == h-1:
check_lowerleft,check_lower,check_lowerright = (False,False,False)
# if on left or right horizontal edge
if x == 0:
check_midleft = False
check_upperleft = False
check_lowerleft = False
if x >= w-1:
check_midright = False
check_upperright = False
check_lowerright = False
num_0 = False
num_1 = False
num_2 = False
num_3 = False
num_4 = False
num_5 = False
num_6 = False
num_7 = False
total_nums = 0
nums0=None
nums1=None
if check_upperleft:
if str(matrix[y-1][x-1]).isnumeric():
num_0 = True
total_nums+=1
if check_upper:
if str(matrix[y-1][x]).isnumeric():
num_1 = True
if not num_0:
total_nums+=1
if check_upperright:
if str(matrix[y-1][x+1]).isnumeric():
num_2 = True
if not num_1:
total_nums+=1
if check_midleft:
if str(matrix[y][x-1]).isnumeric():
num_3 = True
total_nums+=1
if check_midright:
if str(matrix[y][x+1]).isnumeric():
num_4 = True
total_nums+=1
if check_lowerleft:
if str(matrix[y+1][x-1]).isnumeric():
num_5 = True
total_nums+=1
if check_lower:
if str(matrix[y+1][x]).isnumeric():
num_6 = True
if not num_5:
total_nums+=1
if check_lowerright:
if str(matrix[y+1][x+1]).isnumeric():
num_7 = True
if not num_6:
total_nums+=1
if total_nums==2:
if num_0:
if num_1:
if num_2:
#three-digit string
nums0 = f"{matrix[y-1][x-1]}{matrix[y-1][x]}{matrix[y-1][x+1]}"
else: #if num_0, num_1, NOT num_2
if str(matrix[y-1][x-2]).isnumeric():
nums0 = f"{matrix[y-1][x-2]}{matrix[y-1][x-1]}{matrix[y-1][x]}"
else: #if num_0, NOT num_1
#num_0 is true so number is ends on top-left corner
if str(matrix[y-1][x-2]).isnumeric():
if str(matrix[y-1][x-3]).isnumeric():
nums0 = f"{matrix[y-1][x-3]}{matrix[y-1][x-2]}{matrix[y-1][x-1]}"
else:
nums0 = f"{matrix[y-1][x-2]}{matrix[y-1][x-1]}"
else:
nums0 = f"{matrix[y-1][x-1]}"
#check num_2
if num_2:
if str(matrix[y-1][x+2]).isnumeric():
if str(matrix[y-1][x+3]).isnumeric():
nums1 = f"{matrix[y-1][x+1]}{matrix[y-1][x+2]}{matrix[y-1][x+3]}"
else:
nums1 = f"{matrix[y-1][x+1]}{matrix[y-1][x+2]}"
else:
nums1 = f"{matrix[y-1][x+1]}"
else: #if NOT num_0
if num_1: #NOt num_0, num_1
if num_2: #NOT num_0, num_1, num_2
#num 1 and num 2 are numbers so maybe the next digit is too
if str(matrix[y-1][x+2]).isnumeric():
nums0 = f"{matrix[y-1][x]}{matrix[y-1][x+1]}{str(matrix[y-1][x+2])}"
else:
nums0 = f"{matrix[y-1][x]}{matrix[y-1][x+1]}"
else: #if NOT num 0, num 1, NOT num_2
nums0 = f"{matrix[y-1][x]}"
else: #if NOT num0, NOT num_1
if num_2: #if NOT num0, NOT num_1, num_2
if str(matrix[y-1][x+2]).isnumeric():
if str(matrix[y-1][x+3]).isnumeric():
nums0 = f"{matrix[y-1][x+1]}{matrix[y-1][x+2]}{matrix[y-1][x+3]}"
else:
nums0 = f"{matrix[y-1][x+1]}{matrix[y-1][x+2]}"
else:
nums0 = f"{matrix[y-1][x+1]}"
else: #if NOT num0, NOT num_1, NOT num_2
pass
if not nums1 is None:
return int(nums0)*int(nums1)
if num_3:
if str(matrix[y][x-2]).isnumeric():
if str(matrix[y][x-3]).isnumeric():
if nums0 is None:
nums0 = f"{matrix[y][x-3]}{matrix[y][x-2]}{matrix[y][x-1]}"
else:
nums1 = f"{matrix[y][x-3]}{matrix[y][x-2]}{matrix[y][x-1]}"
else:
if nums0 is None:
nums0 = f"{matrix[y][x-2]}{matrix[y][x-1]}"
else:
nums1 = f"{matrix[y][x-2]}{matrix[y][x-1]}"
else:
if nums0 is None:
nums0 = f"{matrix[y][x-1]}"
else:
nums1 = f"{matrix[y][x-1]}"
if not nums1 is None:
return int(nums0)*int(nums1)
if num_4:
if str(matrix[y][x+2]).isnumeric():
if str(matrix[y][x+3]).isnumeric():
if nums0 is None:
nums0 = f"{matrix[y][x+1]}{matrix[y][x+2]}{matrix[y][x+3]}"
else:
nums1 = f"{matrix[y][x+1]}{matrix[y][x+2]}{matrix[y][x+3]}"
else:
if nums0 is None:
nums0 = f"{matrix[y][x+1]}{matrix[y][x+2]}"
else:
nums1 = f"{matrix[y][x+1]}{matrix[y][x+2]}"
else:
if nums0 is None:
nums0 = f"{matrix[y][x+1]}"
else:
nums1 = f"{matrix[y][x+1]}"
if not nums1 is None:
return int(nums0)*int(nums1)
if num_5:
if num_6:
if num_7:
#three-digit string
if nums0 is None:
nums0 = f"{matrix[y+1][x-1]}{matrix[y+1][x]}{matrix[y+1][x+1]}"
else:
nums1 = f"{matrix[y+1][x-1]}{matrix[y+1][x]}{matrix[y+1][x+1]}"
else: #if num_0, num_1, NOT num_2
if str(matrix[y+1][x-2]).isnumeric():
if nums0 is None:
nums0 = f"{matrix[y+1][x-2]}{matrix[y+1][x-1]}{matrix[y+1][x]}"
else:
nums1 = f"{matrix[y+1][x-2]}{matrix[y+1][x-1]}{matrix[y+1][x]}"
else: #if num_0, NOT num_1
#num_0 is true so number is ends on top-left corner
if str(matrix[y+1][x-2]).isnumeric():
if str(matrix[y+1][x-3]).isnumeric():
if nums0 is None:
nums0 = f"{matrix[y+1][x-3]}{matrix[y+1][x-2]}{matrix[y+1][x-1]}"
else:
nums1 = f"{matrix[y+1][x-3]}{matrix[y+1][x-2]}{matrix[y+1][x-1]}"
else:
if nums0 is None:
nums0 = f"{matrix[y+1][x-2]}{matrix[y+1][x-1]}"
else:
nums1 = f"{matrix[y+1][x-2]}{matrix[y+1][x-1]}"
else:
if nums0 is None:
nums0 = f"{matrix[y+1][x-1]}"
else:
nums1 = f"{matrix[y+1][x-1]}"
#check num_2
if num_7:
if str(matrix[y+1][x+2]).isnumeric():
if str(matrix[y+1][x+3]).isnumeric():
nums1 = f"{matrix[y+1][x+1]}{matrix[y+1][x+2]}{matrix[y+1][x+3]}"
else:
nums1 = f"{matrix[y+1][x+1]}{matrix[y+1][x+2]}"
else:
nums1 = f"{matrix[y+1][x+1]}"
else: #if NOT num_0
if num_6: #NOt num_0, num_1
if num_7: #NOT num_0, num_1, num_2
#num 1 and num 2 are numbers so maybe the next digit is too
if str(matrix[y+1][x+2]).isnumeric():
if nums0 is None:
nums0 = f"{matrix[y+1][x]}{matrix[y+1][x+1]}{str(matrix[y+1][x+2])}"
else:
nums1 = f"{matrix[y+1][x]}{matrix[y+1][x+1]}{str(matrix[y+1][x+2])}"
else:
if nums0 is None:
nums0 = f"{matrix[y+1][x]}{matrix[y+1][x+1]}"
else:
nums1 = f"{matrix[y+1][x]}{matrix[y+1][x+1]}"
else: #if NOT num 0, num 1, NOT num_2
if nums0 is None:
nums0 = f"{matrix[y+1][x]}"
else:
nums1 = f"{matrix[y+1][x]}"
else: #if NOT num0, NOT num_1
if num_7: #if NOT num0, NOT num_1, num_2
if str(matrix[y+1][x+2]).isnumeric():
if str(matrix[y+1][x+3]).isnumeric():
if nums0 is None:
nums0 = f"{matrix[y+1][x+1]}{matrix[y+1][x+2]}{matrix[y+1][x+3]}"
else:
nums1 = f"{matrix[y+1][x+1]}{matrix[y+1][x+2]}{matrix[y+1][x+3]}"
else:
if nums0 is None:
nums0 = f"{matrix[y+1][x+1]}{matrix[y+1][x+2]}"
else:
nums1 = f"{matrix[y+1][x+1]}{matrix[y+1][x+2]}"
else:
if nums0 is None:
nums0 = f"{matrix[y+1][x+1]}"
else:
nums1 = f"{matrix[y+1][x+1]}"
else: #if NOT num0, NOT num_1, NOT num_2
pass
if not nums1 is None:
print(f"y {nums0} {nums1} {y}")
return int(nums0)*int(nums1)
return -1
sum = 0
for y in range(h):
for x in range(w):
c = matrix[y][x]
if c == '*':
#check all 8 directions for part numbers
#since we are an asterisk, we don't have to check if numbers in range are valid since they automatically are :3
gear_ratio = check_gear_ratio(x,y)
if not gear_ratio == -1:
sum+=int(gear_ratio)
print(sum)