-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
day_16.py
111 lines (94 loc) · 2.85 KB
/
day_16.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
from math import prod
import aoc_helper
from aoc_helper import range
raw = aoc_helper.fetch(16, 2021)
hex_to_bin = {
"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 parse_packet(bits):
version = int(bits[:3], 2)
type = int(bits[3:6], 2)
if type == 4:
data = []
idx = 6
while True:
segment = bits[idx : idx + 5]
idx += 5
data.append(segment[1:])
if segment[0] == "0":
break
data = int("".join(data), 2)
return idx, (version, type, data)
else:
length_id = bits[6]
if length_id == "0":
packets_len = int(bits[7:22], 2)
packets_substr = bits[22 : 22 + packets_len]
packets = []
while packets_substr:
packet_len, packet = parse_packet(packets_substr)
packets_substr = packets_substr[packet_len:]
packets.append(packet)
return 22 + packets_len, (version, type, packets)
else:
packets_count = int(bits[7:18], 2)
packets_substr = bits[18:]
packets = []
total_len = 18
for _ in range(packets_count):
packet_len, packet = parse_packet(packets_substr)
packets_substr = packets_substr[packet_len:]
total_len += packet_len
packets.append(packet)
return total_len, (version, type, packets)
def parse_raw():
bits = "".join(hex_to_bin[ch] for ch in raw)
return parse_packet(bits)[1]
data = parse_raw()
def part_one():
total = 0
to_search = [data]
while to_search:
packet = to_search.pop()
total += packet[0]
if isinstance(packet[2], list):
to_search.extend(packet[2])
return total
def handle_packet(packet):
version, type, data = packet
match type:
case 0:
return sum(handle_packet(packet) for packet in data)
case 1:
return prod(handle_packet(packet) for packet in data)
case 2:
return min(handle_packet(packet) for packet in data)
case 3:
return max(handle_packet(packet) for packet in data)
case 4:
return data
case 5:
return handle_packet(data[0]) > handle_packet(data[1])
case 6:
return handle_packet(data[0]) < handle_packet(data[1])
case 7:
return handle_packet(data[0]) == handle_packet(data[1])
def part_two():
return handle_packet(data)
aoc_helper.lazy_submit(day=16, year=2021, solution=part_one)
aoc_helper.lazy_submit(day=16, year=2021, solution=part_two)