Compare commits
No commits in common. "1fb9a8416d838a4e8afc49d8fb87150f36791888" and "8739e5cc916c12c776a5f4bbca25974869da94c5" have entirely different histories.
1fb9a8416d
...
8739e5cc91
@ -18,81 +18,6 @@ fn hex(b: &u8) -> u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sum_version(packet: &Packet) -> u64 {
|
|
||||||
fn sum_packets(packets: &[Packet]) -> u64 {
|
|
||||||
packets.iter().map(|p| sum_version(p)).sum()
|
|
||||||
}
|
|
||||||
packet.version as u64
|
|
||||||
+ match &packet.packet_type {
|
|
||||||
PacketType::Sum(packets) => sum_packets(&packets),
|
|
||||||
PacketType::Product(packets) => sum_packets(&packets),
|
|
||||||
PacketType::Minimum(packets) => sum_packets(&packets),
|
|
||||||
PacketType::Maximum(packets) => sum_packets(&packets),
|
|
||||||
PacketType::Literal(_) => 0,
|
|
||||||
PacketType::GreaterThan(packets) => sum_packets(&packets),
|
|
||||||
PacketType::LessThan(packets) => sum_packets(&packets),
|
|
||||||
PacketType::Equal(packets) => sum_packets(&packets),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn interpret(packet: &Packet) -> u64 {
|
|
||||||
match &packet.packet_type {
|
|
||||||
PacketType::Sum(packets) => packets.iter().map(interpret).sum(),
|
|
||||||
PacketType::Product(packets) => packets.iter().map(interpret).product(),
|
|
||||||
PacketType::Minimum(packets) => packets.iter().map(interpret).min().unwrap(),
|
|
||||||
PacketType::Maximum(packets) => packets.iter().map(interpret).max().unwrap(),
|
|
||||||
PacketType::Literal(v) => *v,
|
|
||||||
PacketType::GreaterThan(packets) => {
|
|
||||||
if interpret(&packets[0]) > interpret(&packets[1]) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PacketType::LessThan(packets) => {
|
|
||||||
if interpret(&packets[0]) < interpret(&packets[1]) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PacketType::Equal(packets) => {
|
|
||||||
if interpret(&packets[0]) == interpret(&packets[1]) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum PacketType {
|
|
||||||
// 0
|
|
||||||
Sum(Vec<Packet>),
|
|
||||||
// 1
|
|
||||||
Product(Vec<Packet>),
|
|
||||||
// 2
|
|
||||||
Minimum(Vec<Packet>),
|
|
||||||
// 3
|
|
||||||
Maximum(Vec<Packet>),
|
|
||||||
// 4
|
|
||||||
Literal(u64),
|
|
||||||
// 5
|
|
||||||
GreaterThan(Vec<Packet>),
|
|
||||||
// 6
|
|
||||||
LessThan(Vec<Packet>),
|
|
||||||
// 7
|
|
||||||
Equal(Vec<Packet>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct Packet {
|
|
||||||
version: u64,
|
|
||||||
bit_size: u64,
|
|
||||||
packet_type: PacketType,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Parser<'a> {
|
struct Parser<'a> {
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
tmp: u64,
|
tmp: u64,
|
||||||
@ -109,7 +34,10 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
fn read(&mut self, n: usize) -> u64 {
|
fn read(&mut self, n: usize) -> u64 {
|
||||||
assert!(n < 32, "can't read more than 32 bits at time");
|
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);
|
print!(
|
||||||
|
" BEGIN n {0} tmp 0b{1:b} len {2} - ",
|
||||||
|
n, self.tmp, self.tmp_len
|
||||||
|
);
|
||||||
while self.tmp_len < n {
|
while self.tmp_len < n {
|
||||||
let mut buf = [0; 1];
|
let mut buf = [0; 1];
|
||||||
self.bytes.read_exact(&mut buf).expect("EOF");
|
self.bytes.read_exact(&mut buf).expect("EOF");
|
||||||
@ -125,86 +53,89 @@ impl<'a> Parser<'a> {
|
|||||||
let mask = (1 << self.tmp_len) - 1;
|
let mask = (1 << self.tmp_len) - 1;
|
||||||
self.tmp = self.tmp & mask;
|
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);
|
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
|
v as u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn read_packet(p: &mut Parser) -> (Vec<u64>, u64) {
|
||||||
fn parse_packet(p: &mut Parser) -> Packet {
|
let mut versions = Vec::new();
|
||||||
let mut bit_size: u64 = 0;
|
let mut bits_processed: u64 = 0;
|
||||||
let version = p.read(3);
|
let version = p.read(3);
|
||||||
bit_size += 3;
|
versions.push(version);
|
||||||
let packet_type_id = p.read(3);
|
bits_processed += 3;
|
||||||
bit_size += 3;
|
let typ = p.read(3);
|
||||||
let packet_type = if packet_type_id == 4 {
|
bits_processed += 3;
|
||||||
|
println!("version {} type {}", version, typ);
|
||||||
|
if typ == 4 {
|
||||||
// Literal, read 5 bits at a time until MSB is 0
|
// Literal, read 5 bits at a time until MSB is 0
|
||||||
let mut v = 0;
|
println!("type 4 literal");
|
||||||
loop {
|
loop {
|
||||||
let l = p.read(5);
|
let l = p.read(5);
|
||||||
v = (v << 4) | (l & 0b1111);
|
bits_processed += 5;
|
||||||
bit_size += 5;
|
println!("literal 0b{:05b}", l);
|
||||||
if 0b10000 & l == 0 {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PacketType::Literal(v)
|
|
||||||
} else {
|
} else {
|
||||||
// length type ID
|
// length type ID
|
||||||
let ltid = p.read(1);
|
let ltid = p.read(1);
|
||||||
bit_size += 1;
|
bits_processed += 1;
|
||||||
let mut packets = Vec::new();
|
|
||||||
if ltid == 0 {
|
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.
|
// 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);
|
let len = p.read(15);
|
||||||
bit_size += 15;
|
bits_processed += 15;
|
||||||
|
println!("{} bits in subpacket", len);
|
||||||
let mut sub_bits = 0;
|
let mut sub_bits = 0;
|
||||||
while sub_bits < len {
|
while sub_bits < len {
|
||||||
let sub_p = parse_packet(p);
|
let (vs, bp) = read_packet(p);
|
||||||
bit_size += sub_p.bit_size;
|
versions.extend(vs.iter());
|
||||||
sub_bits += sub_p.bit_size;
|
bits_processed += bp;
|
||||||
packets.push(sub_p);
|
sub_bits += bp;
|
||||||
}
|
}
|
||||||
} else {
|
} 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.
|
// 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);
|
let num = p.read(11);
|
||||||
bit_size += 11;
|
bits_processed += 11;
|
||||||
|
println!("{} subpackets", num);
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let sub_p = parse_packet(p);
|
let (vs, bp) = read_packet(p);
|
||||||
bit_size += sub_p.bit_size;
|
versions.extend(vs.iter());
|
||||||
packets.push(sub_p);
|
bits_processed += bp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match packet_type_id {
|
|
||||||
0 => PacketType::Sum(packets),
|
|
||||||
1 => PacketType::Product(packets),
|
|
||||||
2 => PacketType::Minimum(packets),
|
|
||||||
3 => PacketType::Maximum(packets),
|
|
||||||
5 => PacketType::GreaterThan(packets),
|
|
||||||
6 => PacketType::LessThan(packets),
|
|
||||||
7 => PacketType::Equal(packets),
|
|
||||||
_ => panic!("unknown packet type ID {}", packet_type_id),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Packet {
|
|
||||||
version,
|
|
||||||
bit_size,
|
|
||||||
packet_type,
|
|
||||||
}
|
}
|
||||||
|
return (versions, bits_processed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day16, part1)]
|
#[aoc(day16, part1)]
|
||||||
fn part1(input: &str) -> Result<u64> {
|
fn part1(input: &str) -> Result<u64> {
|
||||||
let mut p = Parser::new(input);
|
let mut p = Parser::new(input);
|
||||||
let packet = parse_packet(&mut p);
|
let (versions, _) = read_packet(&mut p);
|
||||||
Ok(sum_version(&packet))
|
Ok(versions.iter().sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[aoc(day16, part2)]
|
#[aoc(day16, part2)]
|
||||||
fn part2(input: &str) -> Result<u64> {
|
fn part2(input: &str) -> Result<usize> {
|
||||||
let mut p = Parser::new(input);
|
todo!("part2");
|
||||||
let packet = parse_packet(&mut p);
|
Ok(0)
|
||||||
Ok(interpret(&packet))
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -230,25 +161,14 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part2()->Result<()> {
|
fn test_part2()->Result<()> {
|
||||||
let input = vec![
|
let input = r#"
|
||||||
("C200B40A82", 3),
|
"#
|
||||||
("04005AC33890", 54),
|
.trim();
|
||||||
("880086C3E88112", 7),
|
assert_eq!(part2(input)?, usize::MAX);
|
||||||
("CE00C43D881120", 9),
|
|
||||||
("D8005AC2A8F0", 1),
|
|
||||||
("F600BC2D8F", 0),
|
|
||||||
("9C005AC2F8F0", 0),
|
|
||||||
("9C0141080250320F1802104A08", 1),
|
|
||||||
];
|
|
||||||
for (inp, want) in input {
|
|
||||||
print!("\nTesting '{}'\n - ", inp);
|
|
||||||
inp.as_bytes().iter().for_each(|c| print!("{:04b}", hex(c)));
|
|
||||||
println!();
|
|
||||||
assert_eq!(part2(inp)?, want);
|
|
||||||
println!("Passed '{}'", inp);
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user