97 lines
2.4 KiB
Python
97 lines
2.4 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
lines = []
|
||
|
with open('./inputs/day03.txt') as f:
|
||
|
lines = f.readlines()
|
||
|
|
||
|
class Point:
|
||
|
def __init__(self, x, y):
|
||
|
self.x = x
|
||
|
self.y = y
|
||
|
|
||
|
def __str__(self):
|
||
|
return f'({self.x}, {self.y})'
|
||
|
|
||
|
class Number:
|
||
|
def __init__(self, start, end, digits):
|
||
|
self.start = start
|
||
|
self.end = end
|
||
|
self.digits = digits
|
||
|
self.value = int(f''.join(map(str, digits)))
|
||
|
|
||
|
def __str__(self):
|
||
|
return f'({self.start}, {self.end}, {self.digits}, {self.value})'
|
||
|
|
||
|
def adjacentToSymbols(self, symbols):
|
||
|
for symbol in symbols:
|
||
|
if self.adjacentTo(symbol):
|
||
|
return True
|
||
|
|
||
|
return False
|
||
|
|
||
|
def adjacentTo(self, symbol):
|
||
|
if abs(self.start.y - symbol.y) <= 1 and ((self.start.x - 1) <= symbol.x <= (self.end.x + 1)):
|
||
|
return True
|
||
|
|
||
|
return False
|
||
|
|
||
|
class Symbol:
|
||
|
def __init__(self, x, y, value):
|
||
|
self.x = x
|
||
|
self.y = y
|
||
|
self.value = value
|
||
|
|
||
|
def __str__(self):
|
||
|
return f'({self.x}, {self.y}, {self.value})'
|
||
|
|
||
|
def gearRatio(self, numbers):
|
||
|
if not self.value == '*':
|
||
|
return -1
|
||
|
|
||
|
adjacent = []
|
||
|
|
||
|
for number in numbers:
|
||
|
if number.adjacentTo(self):
|
||
|
adjacent.append(number)
|
||
|
|
||
|
if len(adjacent) == 2:
|
||
|
return adjacent[0].value * adjacent[1].value
|
||
|
|
||
|
return -1
|
||
|
|
||
|
# part 1
|
||
|
numbers = []
|
||
|
symbols = []
|
||
|
|
||
|
for y in range(len(lines)):
|
||
|
line = lines[y]
|
||
|
digits = []
|
||
|
numberStarted = False
|
||
|
start = None
|
||
|
end = None
|
||
|
|
||
|
for x in range(len(line)):
|
||
|
ch = line[x]
|
||
|
if (ch == '.' and not numberStarted):
|
||
|
continue
|
||
|
|
||
|
if (ch.isdigit() and not numberStarted):
|
||
|
numberStarted = True
|
||
|
start = Point(x, y)
|
||
|
|
||
|
if (ch.isdigit()):
|
||
|
digits.append(int(ch))
|
||
|
|
||
|
if ((not ch.isdigit()) and numberStarted):
|
||
|
end = Point(x - 1, y)
|
||
|
numbers.append(Number(start, end, digits))
|
||
|
numberStarted = False
|
||
|
digits = []
|
||
|
|
||
|
if ((not ch.isdigit()) and (not ch == '.') and (not ch == '\n')):
|
||
|
symbols.append(Symbol(x, y, ch))
|
||
|
|
||
|
print(f'Part 1: {sum([number.value for number in numbers if number.adjacentToSymbols(symbols)])}')
|
||
|
|
||
|
# part 2
|
||
|
print(f'Part 2: {sum([symbol.gearRatio(numbers) for symbol in symbols if symbol.gearRatio(numbers) > 0])}')
|