-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path16-1.py
executable file
·102 lines (83 loc) · 2.64 KB
/
16-1.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
#!/usr/bin/env python
class Packet:
def __init__(self, version, t):
self.version = version
self.t = t
def score(self):
return self.version
def __str__(self):
return f"<{self.__class__.__name__}: version={self.version}, type={self.t}>"
class Literal(Packet):
def __init__(self, version, t):
super().__init__(version, t)
self.data = -1
def parse(self, bits):
b = ''
while True:
cont = int(bits[0])
group = bits[1:5]
bits = bits[5:]
b += ''.join(group)
if cont == 0:
break
self.data = int(b, 2)
return bits
def __str__(self):
return f"<{self.__class__.__name__}: version={self.version}, type={self.t}, data={self.data}>"
class Operator(Packet):
def __init__(self, version, t):
super().__init__(version, t)
self.sub_packets = []
def parse(self, bits):
length_type_id = int(''.join(bits[0:1]))
bits = bits[1:]
if length_type_id == 0:
sub_packet_length = int(''.join(bits[0:15]), 2)
bits = bits[15:]
self.sub_packets = parse_packets(bits[0:sub_packet_length])
bits = bits[sub_packet_length:]
elif length_type_id == 1:
num_sub_packets = int(''.join(bits[0:11]), 2)
bits = bits[11:]
for _ in range(num_sub_packets):
sub_packet, bits = parse_packet(bits)
self.sub_packets.append(sub_packet)
return bits
def score(self):
score = self.version
for p in self.sub_packets:
score += p.score()
return score
def __str__(self):
s = f"<{self.__class__.__name__}: version={self.version}, type={self.t}, sub_packets=[\n"
for p in self.sub_packets:
s += str(p) + "\n"
s += ">"
return s
def parse_packet(bits):
version = int(''.join(bits[0:3]), 2)
bits = bits[3:]
t = int(''.join(bits[0:3]), 2)
bits = bits[3:]
if t == 4:
packet = Literal(version, t)
else:
packet = Operator(version, t)
bits = packet.parse(bits)
return (packet, bits)
def parse_packets(bits):
packets = []
while not all(b == '0' for b in bits):
packet, bits = parse_packet(bits)
packets.append(packet)
return packets
lines = [list(line.strip()) for line in open('16.input').readlines()]
packets = []
for line in lines:
binary = []
for h in line:
binary += list(format(int(h, 16), '0>4b'))
packets.append(binary)
for p in packets:
packet, _ = parse_packet(p)
print(packet.score())