Part 2 is dumb
This commit is contained in:
parent
b5299b174b
commit
ba3cf04c1e
|
@ -99,7 +99,7 @@ enum BITSValue {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BITSPacket {
|
pub struct BITSPacket {
|
||||||
version: u8,
|
version: u8,
|
||||||
packet_type: u8,
|
op: PacketOp,
|
||||||
inner: BITSValue,
|
inner: BITSValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,27 +109,54 @@ struct ParsedPacket {
|
||||||
packet: BITSPacket,
|
packet: BITSPacket,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum PacketOp {
|
||||||
|
Sum,
|
||||||
|
Product,
|
||||||
|
Minimum,
|
||||||
|
Value,
|
||||||
|
Maximum,
|
||||||
|
GreaterThan,
|
||||||
|
LessThan,
|
||||||
|
EqualTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketOp {
|
||||||
|
pub fn from(b: u64) -> PacketOp {
|
||||||
|
match b {
|
||||||
|
1 => PacketOp::Product,
|
||||||
|
2 => PacketOp::Minimum,
|
||||||
|
3 => PacketOp::Maximum,
|
||||||
|
4 => PacketOp::Value,
|
||||||
|
5 => PacketOp::GreaterThan,
|
||||||
|
6 => PacketOp::LessThan,
|
||||||
|
7 => PacketOp::EqualTo,
|
||||||
|
_ => PacketOp::Sum,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_packet(bytes: &[u8], packet_start_bit: usize) -> Result<ParsedPacket, &'static str> {
|
fn parse_packet(bytes: &[u8], packet_start_bit: usize) -> Result<ParsedPacket, &'static str> {
|
||||||
println!("PARSE PACKET at {}", packet_start_bit);
|
println!("PARSE PACKET at {}", packet_start_bit);
|
||||||
let version = parse_bytes_from_bits(bytes, packet_start_bit, 3)?;
|
let version = parse_bytes_from_bits(bytes, packet_start_bit, 3)?;
|
||||||
let packet_type = parse_bytes_from_bits(bytes, packet_start_bit + 3, 3)?;
|
let op = PacketOp::from(parse_bytes_from_bits(bytes, packet_start_bit + 3, 3)?);
|
||||||
println!("Processing packet with version {0} of type {2} at bit_index {1}", version, packet_start_bit, packet_type);
|
println!("Processing packet with version {0} of type {2:#?} at bit_index {1}", version, packet_start_bit, op);
|
||||||
if packet_type == 4 {
|
if matches!(op, PacketOp::Value) {
|
||||||
let mut bit_index = packet_start_bit + 6;
|
let mut bit_index = packet_start_bit + 6;
|
||||||
let mut value = 0u64;
|
let mut value = 0u64;
|
||||||
loop {
|
loop {
|
||||||
let value_segment = parse_bytes_from_bits(bytes, bit_index, 5)?;
|
let value_segment = parse_bytes_from_bits(bytes, bit_index, 5)?;
|
||||||
value = (value << 4) & (value_segment & 0b1111);
|
value = (value << 4) + value_segment;
|
||||||
println!("Literal Value Segment at {}...", bit_index);
|
println!("Literal Value Segment at {}...", bit_index);
|
||||||
bit_index += 5;
|
bit_index += 5;
|
||||||
if value_segment < 0b10000u64 { break; }
|
if value_segment < 0b10000u64 { break; }
|
||||||
}
|
}
|
||||||
println!("PARSE PACKET DONE (at {})", packet_start_bit);
|
println!("PARSE PACKET DONE (at {}) VALUE: {}", packet_start_bit, value);
|
||||||
Ok(ParsedPacket {
|
Ok(ParsedPacket {
|
||||||
bits_parsed: bit_index - packet_start_bit,
|
bits_parsed: bit_index - packet_start_bit,
|
||||||
packet: BITSPacket {
|
packet: BITSPacket {
|
||||||
version: version.to_le_bytes()[0],
|
version: version.to_le_bytes()[0],
|
||||||
packet_type: packet_type.to_le_bytes()[0],
|
op,
|
||||||
inner: BITSValue::LiteralValue(BITSLiteralValue { value }),
|
inner: BITSValue::LiteralValue(BITSLiteralValue { value }),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -152,7 +179,7 @@ fn parse_packet(bytes: &[u8], packet_start_bit: usize) -> Result<ParsedPacket, &
|
||||||
bits_parsed: 7 + 15 + subpacket_bits,
|
bits_parsed: 7 + 15 + subpacket_bits,
|
||||||
packet: BITSPacket {
|
packet: BITSPacket {
|
||||||
version: version.to_le_bytes()[0],
|
version: version.to_le_bytes()[0],
|
||||||
packet_type: packet_type.to_le_bytes()[0],
|
op,
|
||||||
inner: BITSValue::Operator(BITSOperator {
|
inner: BITSValue::Operator(BITSOperator {
|
||||||
length_type: BITSLengthType::SubpacketCount,
|
length_type: BITSLengthType::SubpacketCount,
|
||||||
length,
|
length,
|
||||||
|
@ -179,7 +206,7 @@ fn parse_packet(bytes: &[u8], packet_start_bit: usize) -> Result<ParsedPacket, &
|
||||||
bits_parsed: bit_index - packet_start_bit,
|
bits_parsed: bit_index - packet_start_bit,
|
||||||
packet: BITSPacket {
|
packet: BITSPacket {
|
||||||
version: version.to_le_bytes()[0],
|
version: version.to_le_bytes()[0],
|
||||||
packet_type: packet_type.to_le_bytes()[0],
|
op,
|
||||||
inner: BITSValue::Operator(BITSOperator {
|
inner: BITSValue::Operator(BITSOperator {
|
||||||
length_type: BITSLengthType::SubpacketBits,
|
length_type: BITSLengthType::SubpacketBits,
|
||||||
length,
|
length,
|
||||||
|
@ -205,13 +232,88 @@ pub fn packet_version_sum(packet: BITSPacket) -> u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn packet_value(packet: BITSPacket) -> u64 {
|
||||||
|
// bytes.iter().for_each(|b| println!("{:#010b}", b));
|
||||||
|
println!("op: {:#?}", packet.op);
|
||||||
|
if let BITSValue::LiteralValue(p) = packet.inner {
|
||||||
|
println!("VALUE: {}", p.value);
|
||||||
|
p.value
|
||||||
|
} else if let BITSValue::Operator(mut p) = packet.inner {
|
||||||
|
match packet.op {
|
||||||
|
PacketOp::Sum => {
|
||||||
|
let mut sum = 0;
|
||||||
|
while !p.subpackets.is_empty() {
|
||||||
|
sum += packet_value(p.subpackets.remove(0));
|
||||||
|
}
|
||||||
|
println!("Sum: {}", sum);
|
||||||
|
sum
|
||||||
|
},
|
||||||
|
PacketOp::Product => {
|
||||||
|
let mut product = packet_value(p.subpackets.remove(0));
|
||||||
|
while !p.subpackets.is_empty() {
|
||||||
|
product *= packet_value(p.subpackets.remove(0));
|
||||||
|
}
|
||||||
|
println!("Product: {}", product);
|
||||||
|
product
|
||||||
|
},
|
||||||
|
PacketOp::Minimum => {
|
||||||
|
let mut min = u64::MAX;
|
||||||
|
while !p.subpackets.is_empty() {
|
||||||
|
min = std::cmp::min(min, packet_value(p.subpackets.remove(0)));
|
||||||
|
}
|
||||||
|
println!("Min: {}", min);
|
||||||
|
min
|
||||||
|
},
|
||||||
|
PacketOp::Maximum => {
|
||||||
|
let mut max = u64::MIN;
|
||||||
|
while !p.subpackets.is_empty() {
|
||||||
|
max = std::cmp::max(max, packet_value(p.subpackets.remove(0)));
|
||||||
|
}
|
||||||
|
println!("Max: {}", max);
|
||||||
|
max
|
||||||
|
},
|
||||||
|
PacketOp::GreaterThan => {
|
||||||
|
let v1 = packet_value(p.subpackets.remove(0));
|
||||||
|
let v2 = packet_value(p.subpackets.remove(0));
|
||||||
|
println!("GT: {} > {} -> {}", v1, v2, u64::from(v1 > v2));
|
||||||
|
u64::from(v1 > v2)
|
||||||
|
},
|
||||||
|
PacketOp::LessThan => {
|
||||||
|
let v1 = packet_value(p.subpackets.remove(0));
|
||||||
|
let v2 = packet_value(p.subpackets.remove(0));
|
||||||
|
println!("LT: {} > {} -> {}", v1, v2, u64::from(v1 < v2));
|
||||||
|
u64::from(v1 < v2)
|
||||||
|
},
|
||||||
|
PacketOp::EqualTo => {
|
||||||
|
let v1 = packet_value(p.subpackets.remove(0));
|
||||||
|
let v2 = packet_value(p.subpackets.remove(0));
|
||||||
|
println!("ET: {} == {} -> {}", v1, v2, u64::from(v1 == v2));
|
||||||
|
u64::from(v1 == v2)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("UH-OH");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("UH-OH");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// part 1
|
||||||
let bytes = hex_string_to_bytes(&day_input(16));
|
let bytes = hex_string_to_bytes(&day_input(16));
|
||||||
bytes.iter().for_each(|b| println!("{:#010b}", b));
|
bytes.iter().for_each(|b| println!("{:#010b}", b));
|
||||||
let packet = parse_packet(&bytes, 0).unwrap().packet;
|
let packet = parse_packet(&bytes, 0).unwrap().packet;
|
||||||
// println!("{:#?}", packet);
|
// println!("{:#?}", packet);
|
||||||
let version_sum = packet_version_sum(packet);
|
let version_sum = packet_version_sum(packet);
|
||||||
println!("Sum of packet versions: {:?}", version_sum);
|
println!("Sum of packet versions (part 1): {:?}", version_sum);
|
||||||
|
|
||||||
|
// println!("{:#?}", packet);
|
||||||
|
let packet2 = parse_packet(&bytes, 0).unwrap().packet;
|
||||||
|
let operation_result = packet_value(packet2);
|
||||||
|
println!("Packet operations result (part 2): {:?}", operation_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -227,6 +329,19 @@ mod tests {
|
||||||
assert_eq!(tester("A0016C880162017C3686B18A3D4780"), 31);
|
assert_eq!(tester("A0016C880162017C3686B18A3D4780"), 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn packet_op_result_examples() {
|
||||||
|
let tester = |s: &str| packet_value(parse_packet(&hex_string_to_bytes(&s.to_string()), 0).unwrap().packet);
|
||||||
|
assert_eq!(tester("C200B40A82"), 3);
|
||||||
|
assert_eq!(tester("04005AC33890"), 54);
|
||||||
|
assert_eq!(tester("880086C3E88112"), 7);
|
||||||
|
assert_eq!(tester("CE00C43D881120"), 9);
|
||||||
|
assert_eq!(tester("D8005AC2A8F0"), 1);
|
||||||
|
assert_eq!(tester("F600BC2D8F"), 0);
|
||||||
|
assert_eq!(tester("9C005AC2F8F0"), 0);
|
||||||
|
assert_eq!(tester("9C0141080250320F1802104A08"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_bytes_from_bits_examples() {
|
fn parse_bytes_from_bits_examples() {
|
||||||
let v: Vec<u8> = vec![0b0011_0011, 0b0100_1111, 0b1101_1011, 0b1001_1010];
|
let v: Vec<u8> = vec![0b0011_0011, 0b0100_1111, 0b1101_1011, 0b1001_1010];
|
||||||
|
|
Loading…
Reference in a new issue