Day 16 part 1
This commit is contained in:
parent
c7a180dee3
commit
8739e5cc91
1
2021/input/2021/day16.txt
Normal file
1
2021/input/2021/day16.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
6051639005B56008C1D9BB3CC9DAD5BE97A4A9104700AE76E672DC95AAE91425EF6AD8BA5591C00F92073004AC0171007E0BC248BE0008645982B1CA680A7A0CC60096802723C94C265E5B9699E7E94D6070C016958F99AC015100760B45884600087C6E88B091C014959C83E740440209FC89C2896A50765A59CE299F3640D300827902547661964D2239180393AF92A8B28F4401BCC8ED52C01591D7E9D2591D7E9D273005A5D127C99802C095B044D5A19A73DC0E9C553004F000DE953588129E372008F2C0169FDB44FA6C9219803E00085C378891F00010E8FF1AE398803D1BE25C743005A6477801F59CC4FA1F3989F420C0149ED9CF006A000084C5386D1F4401F87310E313804D33B4095AFBED32ABF2CA28007DC9D3D713300524BCA940097CA8A4AF9F4C00F9B6D00088654867A7BC8BCA4829402F9D6895B2E4DF7E373189D9BE6BF86B200B7E3C68021331CD4AE6639A974232008E663C3FE00A4E0949124ED69087A848002749002151561F45B3007218C7A8FE600FC228D50B8C01097EEDD7001CF9DE5C0E62DEB089805330ED30CD3C0D3A3F367A40147E8023221F221531C9681100C717002100B36002A19809D15003900892601F950073630024805F400150D400A70028C00F5002C00252600698400A700326C0E44590039687B313BF669F35C9EF974396EF0A647533F2011B340151007637C46860200D43085712A7E4FE60086003E5234B5A56129C91FC93F1802F12EC01292BD754BCED27B92BD754BCED27B100264C4C40109D578CA600AC9AB5802B238E67495391D5CFC402E8B325C1E86F266F250B77ECC600BE006EE00085C7E8DF044001088E31420BCB08A003A72BF87D7A36C994CE76545030047801539F649BF4DEA52CBCA00B4EF3DE9B9CFEE379F14608
|
||||||
174
2021/src/day16.rs
Normal file
174
2021/src/day16.rs
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
use std::{
|
||||||
|
fmt::{Debug, Error, Formatter},
|
||||||
|
io::Read,
|
||||||
|
num::ParseIntError,
|
||||||
|
ops::{Index, IndexMut},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
fn hex(b: &u8) -> u8 {
|
||||||
|
if *b >= b'A' {
|
||||||
|
10 + b - b'A'
|
||||||
|
} else {
|
||||||
|
b - b'0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Parser<'a> {
|
||||||
|
bytes: &'a [u8],
|
||||||
|
tmp: u64,
|
||||||
|
tmp_len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parser<'a> {
|
||||||
|
fn new(input: &str) -> Parser {
|
||||||
|
Parser {
|
||||||
|
bytes: input.as_bytes(),
|
||||||
|
tmp: 0,
|
||||||
|
tmp_len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn read(&mut self, n: usize) -> u64 {
|
||||||
|
assert!(n < 32, "can't read more than 32 bits at time");
|
||||||
|
print!(
|
||||||
|
" BEGIN n {0} tmp 0b{1:b} len {2} - ",
|
||||||
|
n, self.tmp, self.tmp_len
|
||||||
|
);
|
||||||
|
while self.tmp_len < n {
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
self.bytes.read_exact(&mut buf).expect("EOF");
|
||||||
|
// Convert the byte from hexdecimal to binary and merge with any leftover bits.
|
||||||
|
self.tmp = (self.tmp << 4) | hex(&buf[0]) as u64;
|
||||||
|
self.tmp_len += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mask = (1 << n) - 1;
|
||||||
|
self.tmp_len -= n;
|
||||||
|
let v = (self.tmp >> self.tmp_len) & mask;
|
||||||
|
|
||||||
|
let mask = (1 << self.tmp_len) - 1;
|
||||||
|
self.tmp = self.tmp & mask;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
" END n {0} tmp 0b{2:b} len {3} v 0b{1:00$b} ",
|
||||||
|
n, v, self.tmp, self.tmp_len
|
||||||
|
);
|
||||||
|
v as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn read_packet(p: &mut Parser) -> (Vec<u64>, u64) {
|
||||||
|
let mut versions = Vec::new();
|
||||||
|
let mut bits_processed: u64 = 0;
|
||||||
|
let version = p.read(3);
|
||||||
|
versions.push(version);
|
||||||
|
bits_processed += 3;
|
||||||
|
let typ = p.read(3);
|
||||||
|
bits_processed += 3;
|
||||||
|
println!("version {} type {}", version, typ);
|
||||||
|
if typ == 4 {
|
||||||
|
// Literal, read 5 bits at a time until MSB is 0
|
||||||
|
println!("type 4 literal");
|
||||||
|
loop {
|
||||||
|
let l = p.read(5);
|
||||||
|
bits_processed += 5;
|
||||||
|
println!("literal 0b{:05b}", l);
|
||||||
|
if 0b10000 & l == 0 {
|
||||||
|
/*
|
||||||
|
// Read trailing 0s
|
||||||
|
let n = 4 - ((bits_processed) % 4) as usize;
|
||||||
|
println!(
|
||||||
|
"bits processed {}, draining {} trailing 0s",
|
||||||
|
bits_processed, n
|
||||||
|
);
|
||||||
|
let _ = p.read(n);
|
||||||
|
bits_processed += n as u64;
|
||||||
|
*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// length type ID
|
||||||
|
let ltid = p.read(1);
|
||||||
|
bits_processed += 1;
|
||||||
|
if ltid == 0 {
|
||||||
|
// If the length type ID is 0, then the next 15 bits are a number that represents the total length in bits of the sub-packets contained by this packet.
|
||||||
|
let len = p.read(15);
|
||||||
|
bits_processed += 15;
|
||||||
|
println!("{} bits in subpacket", len);
|
||||||
|
let mut sub_bits = 0;
|
||||||
|
while sub_bits < len {
|
||||||
|
let (vs, bp) = read_packet(p);
|
||||||
|
versions.extend(vs.iter());
|
||||||
|
bits_processed += bp;
|
||||||
|
sub_bits += bp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the length type ID is 1, then the next 11 bits are a number that represents the number of sub-packets immediately contained by this packet.
|
||||||
|
let num = p.read(11);
|
||||||
|
bits_processed += 11;
|
||||||
|
println!("{} subpackets", num);
|
||||||
|
for _ in 0..num {
|
||||||
|
let (vs, bp) = read_packet(p);
|
||||||
|
versions.extend(vs.iter());
|
||||||
|
bits_processed += bp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (versions, bits_processed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day16, part1)]
|
||||||
|
fn part1(input: &str) -> Result<u64> {
|
||||||
|
let mut p = Parser::new(input);
|
||||||
|
let (versions, _) = read_packet(&mut p);
|
||||||
|
Ok(versions.iter().sum())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[aoc(day16, part2)]
|
||||||
|
fn part2(input: &str) -> Result<usize> {
|
||||||
|
todo!("part2");
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part1() -> Result<()> {
|
||||||
|
let input = vec![
|
||||||
|
("D2FE28", 6),
|
||||||
|
//("38006F45291200", 1 + 0 + 0),
|
||||||
|
("8A004A801A8002F478", 16),
|
||||||
|
("620080001611562C8802118E34", 12),
|
||||||
|
("C0015000016115A2E0802F182340", 23),
|
||||||
|
("A0016C880162017C3686B18A3D4780", 31),
|
||||||
|
];
|
||||||
|
for (inp, want) in input {
|
||||||
|
print!("\nTesting '{}'\n - ", inp);
|
||||||
|
inp.as_bytes().iter().for_each(|c| print!("{:04b}", hex(c)));
|
||||||
|
println!();
|
||||||
|
assert_eq!(part1(inp)?, want);
|
||||||
|
println!("Passed '{}'", inp);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[test]
|
||||||
|
fn test_part2()->Result<()> {
|
||||||
|
let input = r#"
|
||||||
|
"#
|
||||||
|
.trim();
|
||||||
|
assert_eq!(part2(input)?, usize::MAX);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ pub mod day12;
|
|||||||
pub mod day13;
|
pub mod day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
pub mod day15;
|
pub mod day15;
|
||||||
|
pub mod day16;
|
||||||
pub mod day2;
|
pub mod day2;
|
||||||
pub mod day3;
|
pub mod day3;
|
||||||
pub mod day4;
|
pub mod day4;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user