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)