AdventOfCode/Rust/2021/16.rs

107 lines
2.5 KiB
Rust

#![feature(test)]
type Input = Vec<bool>;
fn setup(input: &str) -> Input {
input
.trim()
.chars()
.flat_map(|c| {
let n = "0123456789ABCDEF".find(c).unwrap();
(0..4).rev().map(move |i| n & (1 << i) > 0)
})
.collect()
}
struct Reader<'a> {
data: &'a [bool],
pos: usize,
}
impl<'a> Reader<'a> {
fn new(data: &'a [bool]) -> Self {
Reader { data, pos: 0 }
}
fn read(&mut self, n: usize) -> u64 {
let mut out = 0;
for _ in 0..n {
if self.pos >= self.data.len() {
break;
}
out <<= 1;
if self.data[self.pos] {
out |= 1;
}
self.pos += 1;
}
out
}
}
struct Result {
version_sum: u64,
value: u64,
}
fn solve(io: &mut Reader) -> Result {
let mut version = io.read(3);
let tid = io.read(3);
if tid == 4 {
let mut lit = 0;
loop {
let c = io.read(1);
lit <<= 4;
lit |= io.read(4);
if c == 0 {
break;
}
}
return Result {
version_sum: version,
value: lit,
};
}
let mut values = vec![];
if io.read(1) == 0 {
let c = io.read(15) as usize + io.pos;
while io.pos < c {
let result = solve(io);
version += result.version_sum;
values.push(result.value);
}
} else {
for _ in 0..io.read(11) {
let result = solve(io);
version += result.version_sum;
values.push(result.value);
}
}
Result {
version_sum: version,
value: match tid {
0 => values.iter().cloned().sum(),
1 => values.iter().cloned().product(),
2 => values.iter().cloned().min().unwrap(),
3 => values.iter().cloned().max().unwrap(),
5 => (values[0] > values[1]) as u64,
6 => (values[0] < values[1]) as u64,
7 => (values[0] == values[1]) as u64,
_ => panic!(),
},
}
}
fn part1(input: &Input) -> u64 {
let mut reader = Reader::new(input);
solve(&mut reader).version_sum
}
fn part2(input: &Input) -> u64 {
let mut reader = Reader::new(input);
solve(&mut reader).value
}
aoc::main!(2021, 16, ex: "1a"[a], "2a"[a], "3a"[a], "4a"[a], "1b"[b], "2b"[b], "3b"[b], "4b"[b], "5b"[b], "6b"[b], "7b"[b], "8b"[b]);