390 lines
14 KiB
Python
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)
|