Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/advent-of-code-2021
Path: blob/main/src/day16.rs
97 views
1
pub fn run() {
2
let input = include_str!("inputs/day16").trim();
3
let packet = BitStream::from_hex(input).read_packet();
4
println!("{}", packet.sum_versions());
5
println!("{}", packet.value());
6
}
7
8
struct BitStream {
9
data: Vec<u8>,
10
index: usize,
11
}
12
13
impl BitStream {
14
fn from_hex(hex_str: &str) -> BitStream {
15
let half_bytes: Vec<_> = hex_str
16
.chars()
17
.map(|ch| ch.to_digit(16).unwrap() as u8)
18
.collect();
19
let data = (0..half_bytes.len())
20
.step_by(2)
21
.map(|i| half_bytes[i] << 4 | half_bytes[i + 1])
22
.collect();
23
BitStream { data, index: 0 }
24
}
25
26
fn read_bits(&mut self, n: usize) -> u32 {
27
let mut res = 0;
28
for _ in 0..n {
29
res = res << 1 | self.read_bit();
30
}
31
res
32
}
33
34
fn read_bit(&mut self) -> u32 {
35
let byte = self.data[self.index / 8];
36
let bit = byte >> (7 - self.index % 8) & 1;
37
self.index += 1;
38
bit as u32
39
}
40
41
fn read_packet(&mut self) -> Packet {
42
let version = self.read_bits(3);
43
let type_id = self.read_bits(3);
44
let content = match type_id {
45
4 => self.read_number(),
46
_ => self.read_operator(),
47
};
48
Packet {
49
version,
50
type_id,
51
content,
52
}
53
}
54
55
fn read_number(&mut self) -> PacketContent {
56
let mut result = 0;
57
loop {
58
let group = self.read_bits(5) as u64;
59
result = result << 4 | (group & 0b1111);
60
if group >> 4 == 0 {
61
break;
62
}
63
}
64
PacketContent::Number(result)
65
}
66
67
fn read_operator(&mut self) -> PacketContent {
68
let length_type_id = self.read_bit();
69
let mut sub_packets = vec![];
70
match length_type_id {
71
0 => {
72
let bit_length = self.read_bits(15) as usize;
73
let initial_index = self.index;
74
while self.index < initial_index + bit_length {
75
sub_packets.push(self.read_packet());
76
}
77
}
78
1 => {
79
let packet_length = self.read_bits(11);
80
for _ in 0..packet_length {
81
sub_packets.push(self.read_packet());
82
}
83
}
84
_ => unreachable!(),
85
}
86
PacketContent::Operator(sub_packets)
87
}
88
}
89
90
struct Packet {
91
version: u32,
92
type_id: u32,
93
content: PacketContent,
94
}
95
96
enum PacketContent {
97
Number(u64),
98
Operator(Vec<Packet>),
99
}
100
101
impl Packet {
102
fn sum_versions(&self) -> u32 {
103
match &self.content {
104
PacketContent::Number(_) => self.version,
105
PacketContent::Operator(sub_packets) => {
106
self.version + sub_packets.iter().map(Packet::sum_versions).sum::<u32>()
107
}
108
}
109
}
110
111
fn value(&self) -> u64 {
112
match &self.content {
113
PacketContent::Number(n) => *n,
114
PacketContent::Operator(sub_packets) => {
115
let values: Vec<_> = sub_packets.iter().map(Packet::value).collect();
116
match self.type_id {
117
0 => values.iter().sum(),
118
1 => values.iter().fold(1, |a, b| a * b),
119
2 => *values.iter().min().unwrap(),
120
3 => *values.iter().max().unwrap(),
121
5 => (values[0] > values[1]) as u64,
122
6 => (values[0] < values[1]) as u64,
123
7 => (values[0] == values[1]) as u64,
124
_ => unreachable!(),
125
}
126
}
127
}
128
}
129
}
130
131