-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
174 lines (122 loc) · 3.25 KB
/
main.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
h2b = {
"0": "0000",
"1": "0001",
"2": "0010",
"3": "0011",
"4": "0100",
"5": "0101",
"6": "0110",
"7": "0111",
"8": "1000",
"9": "1001",
"A": "1010",
"B": "1011",
"C": "1100",
"D": "1101",
"E": "1110",
"F": "1111",
}
def to_bin(hex):
result = []
for char in hex:
result.append(h2b[char])
return [c for c in "".join(result)]
def eat(stream, length):
for _ in range(length):
stream.pop(0)
def read_version(stream):
version = stream[:3]
eat(stream, 3)
return int("".join(version), 2)
def read_type(stream):
tpe = stream[:3]
eat(stream, 3)
return int("".join(tpe), 2)
def read_literal_group(stream):
eat(stream, 1) # leading 1 or 0
group = stream[:4]
eat(stream, 4)
return "".join(group)
def read_literal(stream):
literal = []
count = 1
while stream[0] == "1":
count += 1
literal_group = read_literal_group(stream)
literal.append(literal_group)
# 0-prefixed group
literal_group = read_literal_group(stream)
literal.append(literal_group)
res = int("".join(literal), 2)
return res
def read_length_type(stream):
length_type = stream[0]
eat(stream, 1)
return length_type
def read_operator_size(stream):
size = stream[:15]
eat(stream, 15)
return int("".join(size), 2)
def read_operator_number(stream):
number = stream[:11]
eat(stream, 11)
return int("".join(number), 2)
def read_operator_0(stream):
size = read_operator_size(stream)
subpackets = []
stream_length_before = len(stream)
while stream_length_before - size < len(stream):
subpacket = read_packet(stream)
subpackets.append(subpacket)
return subpackets
def read_operator_1(stream):
number = read_operator_number(stream)
subpackets = []
for _ in range(number):
subpacket = read_packet(stream)
subpackets.append(subpacket)
return subpackets
def read_operator(stream):
length_type = read_length_type(stream)
if length_type == "0":
subpackets = read_operator_0(stream)
else:
subpackets = read_operator_1(stream)
return subpackets
def product(numbers):
result = 1
for number in numbers:
result *= number
return result
def read_packet(stream):
version = read_version(stream)
tpe = read_type(stream)
global cumulative_version_numbers
cumulative_version_numbers += version
# literal
if tpe == 4:
return read_literal(stream)
# operator
else:
numbers = read_operator(stream)
if tpe == 0:
return sum(numbers)
elif tpe == 1:
return product(numbers)
elif tpe == 2:
return min(numbers)
elif tpe == 3:
return max(numbers)
elif tpe == 5:
return int(1 if numbers[0] > numbers[1] else 0)
elif tpe == 6:
return int(1 if numbers[0] < numbers[1] else 0)
elif tpe == 7:
return int(numbers[0] == numbers[1])
cumulative_version_numbers = 0
with open("1.in") as f:
hx = f.read()
bn = to_bin(hx)
result = read_packet(bn)
print("part1:", cumulative_version_numbers)
print("part2:", result)