From 0220f88e27bbd6bcb4f3a87141e45648f1051444 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 16 Dec 2021 20:36:23 +0100 Subject: [PATCH] 2021 day16/rust: clean up --- 2021/day16/day16_rs/src/main.rs | 87 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/2021/day16/day16_rs/src/main.rs b/2021/day16/day16_rs/src/main.rs index de91976..0f4e01d 100644 --- a/2021/day16/day16_rs/src/main.rs +++ b/2021/day16/day16_rs/src/main.rs @@ -7,7 +7,6 @@ use std::{ use nom::{ bits::complete as bits, - combinator::flat_map, multi::{many0, many_m_n}, }; use nom::{combinator::map, sequence::pair}; @@ -53,58 +52,64 @@ enum PacketType { } impl PacketType { - pub fn parse(input: Input) -> IResult { - flat_map(bits::take(3_usize), |type_id: u8| { - move |i| match Operator::try_from(type_id) { - Ok(operator) => map(Self::operation_inner, |sub_packets| PacketType::Operation { + pub fn parse(i: Input) -> IResult { + let (i, operator) = map(bits::take(3_usize), |type_id: u8| { + Operator::try_from(type_id) + })(i)?; + + match operator { + Ok(operator) => map(Self::parse_sub_packets, |sub_packets| { + PacketType::Operation { operator, sub_packets, - })(i), - Err(_) => map(Self::literal_inner, PacketType::Literal)(i), - } - })(input) + } + })(i), + Err(_) => map(Self::parse_literal_value, PacketType::Literal)(i), + } } - fn operation_inner(i: Input) -> IResult> { + fn parse_sub_packets(i: Input) -> IResult> { enum LengthType { - Bits(u16), - Packets(u16), + Bits(usize), + Packets(usize), } - flat_map( - flat_map(bits::take(1_usize), |length_type_id: u8| { - move |i| match length_type_id { + impl LengthType { + pub fn parse(i: Input) -> IResult { + let (i, length_type_id) = bits::take(1_usize)(i)?; + match length_type_id { 0 => map(bits::take(15_usize), LengthType::Bits)(i), 1 => map(bits::take(11_usize), LengthType::Packets)(i), _ => unreachable!(), } - }), - |length_type| { - move |i| match length_type { - LengthType::Packets(n) => { - many_m_n(usize::from(n), usize::from(n), Packet::parse)(i) - } - LengthType::Bits(n) => { - // map_parser(recognize(bits::take(n)), many1(Packet::parse))(i) - let extra_bytes_required = (usize::from(n) + i.1) / 8; - let extra_bits_required = (usize::from(n) + i.1) % 8; + } + } - let subpackets_slice = (&i.0[..=extra_bytes_required], i.1); - let (subpackets_end, subpackets) = many0(Packet::parse)(subpackets_slice)?; - if subpackets_end.0.len() > 1 { - todo!() - } - Ok(( - (&i.0[extra_bytes_required..], extra_bits_required), - subpackets, - )) - } - } - }, - )(i) + let (i, length_type) = LengthType::parse(i)?; + match length_type { + LengthType::Packets(n) => many_m_n(n, n, Packet::parse)(i), + LengthType::Bits(n) => { + // manual implementation of something like the following: + // map_parser(recognize(bits::take(n)), many0(Packet::parse))(i) + + let new_byte_offset = (n + i.1) / 8; + let new_bit_offset = (n + i.1) % 8; + + let subpackets_input = (&i.0[..=new_byte_offset], i.1); + let (subpackets_end, subpackets) = many0(Packet::parse)(subpackets_input)?; + + let new_input = (&i.0[new_byte_offset..], new_bit_offset); + assert_eq!(subpackets_end, new_input); + + Ok(( + new_input, + subpackets, + )) + } + } } - fn literal_inner(i: Input) -> IResult { + fn parse_literal_value(i: Input) -> IResult { fold_till( pair(bits::take(1_usize), bits::take(4_usize)), || 0, @@ -122,8 +127,8 @@ impl PacketType { match self { Self::Literal(n) => *n, Self::Operation { - ref operator, - ref sub_packets, + operator, + sub_packets, } => operator.evaluate(sub_packets.iter().map(|p| p.typ.evaluate())), } }