advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.rs (4377B)

    1 #[derive(Debug, Clone)]
    2 enum PacketContent {
    3     Literal(u64),
    4     SubPackets(Vec<Packet>),
    5 }
    6 
    7 #[derive(Debug, Clone)]
    8 struct Packet {
    9     version: u32,
   10     type_id: u32,
   11     content: PacketContent,
   12 }
   13 
   14 fn read_bits(buf: &[u8], cursor: &mut usize, span: usize) -> u32 {
   15     let mut value: u32 = 0;
   16     for _ in 0..span {
   17         let buf_idx = *cursor / 4;
   18         let offset = 3 - *cursor % 4;
   19         value <<= 1;
   20         value += (buf[buf_idx] & (1 << offset)) as u32 >> offset;
   21         *cursor += 1;
   22     }
   23     value
   24 }
   25 
   26 impl Packet {
   27     fn parse(buf: &[u8], start: usize) -> (Packet, usize) {
   28         let mut cursor = start;
   29         let version = read_bits(buf, &mut cursor, 3);
   30         let type_id = read_bits(buf, &mut cursor, 3);
   31         match type_id {
   32             4 => {
   33                 let mut value = 0;
   34                 loop {
   35                     let is_last = read_bits(buf, &mut cursor, 1);
   36                     value = (value << 4) + read_bits(buf, &mut cursor, 4) as u64;
   37                     if is_last == 0 {
   38                         return (
   39                             Packet {
   40                                 version,
   41                                 type_id,
   42                                 content: PacketContent::Literal(value),
   43                             },
   44                             cursor,
   45                         );
   46                     }
   47                 }
   48             }
   49             _ => {
   50                 let mut sub_packets = Vec::new();
   51                 let length_type_id = read_bits(buf, &mut cursor, 1);
   52                 match length_type_id {
   53                     0 => {
   54                         let parse_span = read_bits(buf, &mut cursor, 15);
   55                         let parse_end = cursor + parse_span as usize;
   56                         while cursor < parse_end {
   57                             let (sub_packet, cursor_new) = Self::parse(buf, cursor);
   58                             sub_packets.push(sub_packet);
   59                             cursor = cursor_new;
   60                         }
   61                     }
   62                     1 => {
   63                         let subpacket_count = read_bits(buf, &mut cursor, 11) as usize;
   64                         while sub_packets.len() < subpacket_count {
   65                             let (sub_packet, cursor_new) = Self::parse(buf, cursor);
   66                             sub_packets.push(sub_packet);
   67                             cursor = cursor_new;
   68                         }
   69                     }
   70                     _ => unreachable!(),
   71                 }
   72                 return (
   73                     Packet {
   74                         version,
   75                         type_id,
   76                         content: PacketContent::SubPackets(sub_packets),
   77                     },
   78                     cursor,
   79                 );
   80             }
   81         }
   82     }
   83 }
   84 
   85 fn main() {
   86     let input = std::fs::read_to_string("input.txt")
   87         .unwrap()
   88         .trim()
   89         .chars()
   90         .map(|c| c.to_digit(16).unwrap() as u8)
   91         .collect::<Vec<u8>>();
   92     // 866
   93     println!("Part 1: {}", part_1(&input));
   94     // 1392637195518
   95     println!("Part 2: {}", part_2(&input));
   96 }
   97 
   98 fn calc_version_sum(packet: &Packet) -> u32 {
   99     let mut version_sum = packet.version;
  100     if let PacketContent::SubPackets(sub_packets) = &packet.content {
  101         version_sum += sub_packets.iter().map(calc_version_sum).sum::<u32>();
  102     }
  103     version_sum
  104 }
  105 
  106 fn part_1(buf: &[u8]) -> u32 {
  107     let (packet, _) = Packet::parse(buf, 0);
  108     calc_version_sum(&packet)
  109 }
  110 
  111 fn eval_packet(packet: &Packet) -> u64 {
  112     match &packet.content {
  113         PacketContent::Literal(value) => *value as u64,
  114         PacketContent::SubPackets(sub_packets) => match packet.type_id {
  115             0 => sub_packets.iter().map(eval_packet).sum(),
  116             1 => sub_packets.iter().map(eval_packet).product(),
  117             2 => sub_packets.iter().map(eval_packet).min().unwrap(),
  118             3 => sub_packets.iter().map(eval_packet).max().unwrap(),
  119             5 => (eval_packet(&sub_packets[0]) > eval_packet(&sub_packets[1])) as u64,
  120             6 => (eval_packet(&sub_packets[0]) < eval_packet(&sub_packets[1])) as u64,
  121             7 => (eval_packet(&sub_packets[0]) == eval_packet(&sub_packets[1])) as u64,
  122             _ => unreachable!(),
  123         },
  124     }
  125 }
  126 
  127 fn part_2(buf: &[u8]) -> u64 {
  128     let (packet, _) = Packet::parse(buf, 0);
  129     eval_packet(&packet)
  130 }