Added day 16

This commit is contained in:
Sebastian 2021-12-16 14:26:37 +01:00
parent dceca0e77f
commit 837ee1b9a3
3 changed files with 197 additions and 10 deletions

1
inputs/day16.txt Normal file
View File

@ -0,0 +1 @@
220D6448300428021F9EFE668D3F5FD6025165C00C602FC980B45002A40400B402548808A310028400C001B5CC00B10029C0096011C0003C55003C0028270025400C1002E4F19099F7600142C801098CD0761290021B19627C1D3007E33C4A8A640143CE85CB9D49144C134927100823275CC28D9C01234BD21F8144A6F90D1B2804F39B972B13D9D60939384FE29BA3B8803535E8DF04F33BC4AFCAFC9E4EE32600C4E2F4896CE079802D4012148DF5ACB9C8DF5ACB9CD821007874014B4ECE1A8FEF9D1BCC72A293A0E801C7C9CA36A5A9D6396F8FCC52D18E91E77DD9EB16649AA9EC9DA4F4600ACE7F90DFA30BA160066A200FC448EB05C401B8291F22A2002051D247856600949C3C73A009C8F0CA7FBCCF77F88B0000B905A3C1802B3F7990E8029375AC7DDE2DCA20C2C1004E4BE9F392D0E90073D31634C0090667FF8D9E667FF8D9F0C01693F8FE8024000844688FF0900010D8EB0923A9802903F80357100663DC2987C0008744F8B5138803739EB67223C00E4CC74BA46B0AD42C001DE8392C0B0DE4E8F660095006AA200EC198671A00010E87F08E184FCD7840289C1995749197295AC265B2BFC76811381880193C8EE36C324F95CA69C26D92364B66779D63EA071008C360098002191A637C7310062224108C3263A600A49334C19100A1A000864728BF0980010E8571EE188803D19A294477008A595A53BC841526BE313D6F88CE7E16A7AC60401A9E80273728D2CC53728D2CCD2AA2600A466A007CE680E5E79EFEB07360041A6B20D0F4C021982C966D9810993B9E9F3B1C7970C00B9577300526F52FCAB3DF87EC01296AFBC1F3BC9A6200109309240156CC41B38015796EABCB7540804B7C00B926BD6AC36B1338C4717E7D7A76378C85D8043F947C966593FD2BBBCB27710E57FDF6A686E00EC229B4C9247300528029393EC3BAA32C9F61DD51925AD9AB2B001F72B2EE464C0139580D680232FA129668

View File

@ -1,10 +1 @@
1163751742
1381373672
2136511328
3694931569
7463417111
1319128137
1359912421
3125421639
1293138521
2311944581
8A004A801A8002F478

195
src/bin/day16.rs Normal file
View File

@ -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<bool> {
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<Packet>),
}
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<bool> = 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<Packet> = 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<Packet> = 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<dyn Error>> {
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(())
}