From 837ee1b9a36d2a6f081a30020478e48f631c24be Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Thu, 16 Dec 2021 14:26:37 +0100 Subject: [PATCH] Added day 16 --- inputs/day16.txt | 1 + inputs/sample.txt | 11 +-- src/bin/day16.rs | 195 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 inputs/day16.txt create mode 100644 src/bin/day16.rs diff --git a/inputs/day16.txt b/inputs/day16.txt new file mode 100644 index 0000000..2243276 --- /dev/null +++ b/inputs/day16.txt @@ -0,0 +1 @@ +220D6448300428021F9EFE668D3F5FD6025165C00C602FC980B45002A40400B402548808A310028400C001B5CC00B10029C0096011C0003C55003C0028270025400C1002E4F19099F7600142C801098CD0761290021B19627C1D3007E33C4A8A640143CE85CB9D49144C134927100823275CC28D9C01234BD21F8144A6F90D1B2804F39B972B13D9D60939384FE29BA3B8803535E8DF04F33BC4AFCAFC9E4EE32600C4E2F4896CE079802D4012148DF5ACB9C8DF5ACB9CD821007874014B4ECE1A8FEF9D1BCC72A293A0E801C7C9CA36A5A9D6396F8FCC52D18E91E77DD9EB16649AA9EC9DA4F4600ACE7F90DFA30BA160066A200FC448EB05C401B8291F22A2002051D247856600949C3C73A009C8F0CA7FBCCF77F88B0000B905A3C1802B3F7990E8029375AC7DDE2DCA20C2C1004E4BE9F392D0E90073D31634C0090667FF8D9E667FF8D9F0C01693F8FE8024000844688FF0900010D8EB0923A9802903F80357100663DC2987C0008744F8B5138803739EB67223C00E4CC74BA46B0AD42C001DE8392C0B0DE4E8F660095006AA200EC198671A00010E87F08E184FCD7840289C1995749197295AC265B2BFC76811381880193C8EE36C324F95CA69C26D92364B66779D63EA071008C360098002191A637C7310062224108C3263A600A49334C19100A1A000864728BF0980010E8571EE188803D19A294477008A595A53BC841526BE313D6F88CE7E16A7AC60401A9E80273728D2CC53728D2CCD2AA2600A466A007CE680E5E79EFEB07360041A6B20D0F4C021982C966D9810993B9E9F3B1C7970C00B9577300526F52FCAB3DF87EC01296AFBC1F3BC9A6200109309240156CC41B38015796EABCB7540804B7C00B926BD6AC36B1338C4717E7D7A76378C85D8043F947C966593FD2BBBCB27710E57FDF6A686E00EC229B4C9247300528029393EC3BAA32C9F61DD51925AD9AB2B001F72B2EE464C0139580D680232FA129668 diff --git a/inputs/sample.txt b/inputs/sample.txt index ab80887..0d2cbff 100644 --- a/inputs/sample.txt +++ b/inputs/sample.txt @@ -1,10 +1 @@ -1163751742 -1381373672 -2136511328 -3694931569 -7463417111 -1319128137 -1359912421 -3125421639 -1293138521 -2311944581 +8A004A801A8002F478 diff --git a/src/bin/day16.rs b/src/bin/day16.rs new file mode 100644 index 0000000..062bcec --- /dev/null +++ b/src/bin/day16.rs @@ -0,0 +1,195 @@ +use std::cmp::Ordering; +use std::collections::BinaryHeap; +use std::collections::HashMap; +use std::collections::HashSet; +use std::error::Error; +use std::fs::File; +use std::io::{self, BufRead}; +use std::vec::Vec; + +fn expand_digits(line: &str) -> Vec { + let mut bin = Vec::new(); + + for c in line.chars() { + let bits = match c { + '0' => [false, false, false, false], + '1' => [false, false, false, true], + '2' => [false, false, true, false], + '3' => [false, false, true, true], + '4' => [false, true, false, false], + '5' => [false, true, false, true], + '6' => [false, true, true, false], + '7' => [false, true, true, true], + '8' => [true, false, false, false], + '9' => [true, false, false, true], + 'A' => [true, false, true, false], + 'B' => [true, false, true, true], + 'C' => [true, true, false, false], + 'D' => [true, true, false, true], + 'E' => [true, true, true, false], + 'F' => [true, true, true, true], + _ => panic!("Unsupported char {}", c), + }; + + bin.extend_from_slice(&bits); + } + + bin +} + +fn print_binary(bin: &[bool]) { + for bit in bin.iter() { + if *bit { + print!("1"); + } else { + print!("0"); + } + } + println!(""); +} + +fn bits_to_uint(bits: &[bool]) -> u64 { + let mut base = 1; + let mut res = 0; + for bit in bits.iter().rev() { + if *bit { + res += base; + } + base *= 2; + } + + res +} + +enum Packet { + Literal(u64, u64, u64), + Operator(u64, u64, Vec), +} + +fn parse_packet(bits: &[bool]) -> (Packet, &[bool]) { + let version = bits_to_uint(&bits[0..3]); + let type_id = bits_to_uint(&bits[3..6]); + println!("Version: {}", version); + println!("Type: {}", type_id); + + //Literal value + if type_id == 4 { + let mut tail = &bits[6..]; + let mut res: Vec = Vec::new(); + loop { + let chunk = &tail[0..5]; + tail = &tail[5..]; + res.extend_from_slice(&chunk[1..5]); + if !chunk[0] { + break; + } + } + let literal = bits_to_uint(&res); + println!("Literal {}", literal); + return (Packet::Literal(version, type_id, literal), tail); + } else { + if !bits[6] { + let bit_lenght = bits_to_uint(&bits[7..22]) as usize; + println!("15 bits, bit lenght {}", bit_lenght); + + let mut sub_packets = &bits[22..22 + bit_lenght]; + let tail = &bits[22 + bit_lenght..]; + + let mut packets: Vec = Vec::new(); + while sub_packets.len() >= 11 { + let (packet, rest) = parse_packet(sub_packets); + packets.push(packet); + sub_packets = rest; + } + + return (Packet::Operator(version, type_id, packets), tail); + } else { + let packet_lenght = bits_to_uint(&bits[7..18]) as usize; + println!("11 bits, number of packets {}", packet_lenght); + + let mut tail = &bits[18..]; + + let mut packets: Vec = Vec::new(); + for _ in 0..packet_lenght { + let (packet, rest) = parse_packet(tail); + packets.push(packet); + tail = rest; + } + + return (Packet::Operator(version, type_id, packets), tail); + } + } +} + +fn add_versions(packet: &Packet) -> u64 { + match packet { + Packet::Literal(version, _, _) => *version, + Packet::Operator(version, _, sub_packets) => { + version + + sub_packets + .iter() + .map(|p| add_versions(p)) + .fold(0, |a, b| a + b) + } + } +} + +fn execute_packet(packet: &Packet) -> u64 { + match packet { + Packet::Literal(_, _, value) => *value, + Packet::Operator(_, type_id, sub_packets) => match type_id { + 0 => sub_packets + .iter() + .map(|p| execute_packet(p)) + .fold(0, |a, b| a + b), // sum + 1 => sub_packets + .iter() + .map(|p| execute_packet(p)) + .fold(1, |a, b| a * b), // product + 2 => sub_packets.iter().map(|p| execute_packet(p)).min().unwrap(), // min + 3 => sub_packets.iter().map(|p| execute_packet(p)).max().unwrap(), // max + 5 => { + if execute_packet(&sub_packets[0]) > execute_packet(&sub_packets[1]) { + 1 + } else { + 0 + } + } + 6 => { + if execute_packet(&sub_packets[0]) < execute_packet(&sub_packets[1]) { + 1 + } else { + 0 + } + } + 7 => { + if execute_packet(&sub_packets[0]) == execute_packet(&sub_packets[1]) { + 1 + } else { + 0 + } + } + _ => panic!("Unsupported packet type {}", type_id), + }, + } +} + +fn main() -> Result<(), Box> { + let file = File::open("inputs/day16.txt")?; + let line: String = io::BufReader::new(file).lines().next().unwrap()?; + + let data = expand_digits(&line); + print_binary(&data); + + let (packet, _) = parse_packet(&data); + + let answer1 = add_versions(&packet); + + println!("Answer1: {}", answer1); + + let answer2 = execute_packet(&packet); + + println!("Answer2: {}", answer2); + + Ok(()) +}