-
Notifications
You must be signed in to change notification settings - Fork 1
/
03-2.py
executable file
·79 lines (61 loc) · 2.08 KB
/
03-2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env python
from collections import namedtuple
class Number:
def __init__(self, x, y):
self.left = x
self.right = x
self.up = y
self.down = y
self.value = 0
def add_digit(self, digit, x, y):
self.value = self.value * 10 + int(digit)
self.right = x
def is_adjacent(self, pos):
return pos.x >= self.left - 1 and \
pos.x <= self.right + 1 and \
pos.y >= self.up - 1 and \
pos.y <= self.down + 1
def __str__(self):
return f"<{self.__class__.__name__}: {self.value}, l: {self.left}, r: {self.right}, u: {self.up}, d:{self.down}>"
class Gear:
def __init__(self, pos):
self.pos = pos
self.parts = []
def add_part(self, num):
self.parts.append(num)
def is_valid(self):
return len(self.parts) == 2
def ratio(self):
return self.parts[0].value * self.parts[1].value
def __str__(self):
return f"<{self.__class__.__name__}: valid: {self.is_valid()}, x: {self.pos.x}, y: {self.pos.y}, parts: {self.parts}>"
input = [row.strip() for row in open('03.input').readlines()]
numbers = []
symbols = []
gears = []
for y in range(len(input)):
current_number = None
row = input[y]
for x in range(len(row)):
char = row[x]
match char:
case '.':
current_number = None
case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9':
if not current_number:
current_number = Number(x, y)
numbers.append(current_number)
current_number.add_digit(char, x, y)
case _:
current_number = None
pos = namedtuple('Position', ['x', 'y'])
pos.x = x
pos.y = y
symbols.append(pos)
if char == '*':
gears.append(Gear(pos))
for gear in gears:
for num in numbers:
if num.is_adjacent(gear.pos):
gear.add_part(num)
print(sum([g.ratio() for g in gears if g.is_valid()]))