diff --git a/Cargo.lock b/Cargo.lock index 82780e0..b620f0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", + "bitvec 0.22.3", "rand", ] @@ -130,14 +131,26 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.19.6" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" +checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" dependencies = [ "funty", - "radium", + "radium 0.5.3", "tap", - "wyz", + "wyz 0.2.0", +] + +[[package]] +name = "bitvec" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" +dependencies = [ + "funty", + "radium 0.6.2", + "tap", + "wyz 0.4.0", ] [[package]] @@ -336,9 +349,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "funty" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" [[package]] name = "generic-array" @@ -470,12 +483,11 @@ dependencies = [ [[package]] name = "nom" -version = "6.2.1" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" +checksum = "3d521ee2250f619dd5e06515ba405858d249edc8fae9ddee2dba0695e57db01b" dependencies = [ - "bitvec", - "funty", + "bitvec 0.19.4", "lexical-core", "memchr", "version_check", @@ -570,6 +582,12 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" +[[package]] +name = "radium" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" + [[package]] name = "rand" version = "0.8.4" @@ -913,3 +931,12 @@ name = "wyz" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "wyz" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" +dependencies = [ + "tap", +] diff --git a/aoc2021/Cargo.toml b/aoc2021/Cargo.toml index 4d8f362..e31557d 100644 --- a/aoc2021/Cargo.toml +++ b/aoc2021/Cargo.toml @@ -10,6 +10,7 @@ edition = "2021" aoc = { path = "../aoc" } anyhow = "1.0" rand = "0.8" +bitvec = "0.22" [lib] path = "src/lib.rs" diff --git a/aoc2021/input/day16.txt b/aoc2021/input/day16.txt new file mode 100644 index 0000000..dbbec6c --- /dev/null +++ b/aoc2021/input/day16.txt @@ -0,0 +1 @@ +E20D4100AA9C0199CA6A3D9D6352294D47B3AC6A4335FBE3FDD251003873657600B46F8DC600AE80273CCD2D5028B6600AF802B2959524B727D8A8CC3CCEEF3497188C017A005466DAA6FDB3A96D5944C014C006865D5A7255D79926F5E69200A164C1A65E26C867DDE7D7E4794FE72F3100C0159A42952A7008A6A5C189BCD456442E4A0A46008580273ADB3AD1224E600ACD37E802200084C1083F1540010E8D105A371802D3B845A0090E4BD59DE0E52FFC659A5EBE99AC2B7004A3ECC7E58814492C4E2918023379DA96006EC0008545B84B1B00010F8E915E1E20087D3D0E577B1C9A4C93DD233E2ECF65265D800031D97C8ACCCDDE74A64BD4CC284E401444B05F802B3711695C65BCC010A004067D2E7C4208A803F23B139B9470D7333B71240050A20042236C6A834600C4568F5048801098B90B626B00155271573008A4C7A71662848821001093CB4A009C77874200FCE6E7391049EB509FE3E910421924D3006C40198BB11E2A8803B1AE2A4431007A15C6E8F26009E002A725A5292D294FED5500C7170038C00E602A8CC00D60259D008B140201DC00C401B05400E201608804D45003C00393600B94400970020C00F6002127128C0129CDC7B4F46C91A0084E7C6648DC000DC89D341B23B8D95C802D09453A0069263D8219DF680E339003032A6F30F126780002CC333005E8035400042635C578A8200DC198890AA46F394B29C4016A4960C70017D99D7E8AF309CC014FCFDFB0FE0DA490A6F9D490010567A3780549539ED49167BA47338FAAC1F3005255AEC01200043A3E46C84E200CC4E895114C011C0054A522592912C9C8FDE10005D8164026C70066C200C4618BD074401E8C90E23ACDFE5642700A6672D73F285644B237E8CCCCB77738A0801A3CFED364B823334C46303496C940 diff --git a/aoc2021/src/day16.rs b/aoc2021/src/day16.rs new file mode 100644 index 0000000..53dec9e --- /dev/null +++ b/aoc2021/src/day16.rs @@ -0,0 +1,129 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; +use bitvec::prelude::*; + +const INPUT: &str = include_str!("../input/day16.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let packet: Packet = input.parse()?; + + Ok(packet.version_sum()) +} + +#[derive(PartialEq, Eq, Debug)] +enum PacketType { + Litteral(LitteralPacket), + Operator(OperatorPacket), +} + +#[derive(PartialEq, Eq, Debug)] +struct Packet { + version: u8, + type_id: u8, + packet: PacketType, +} + +impl Packet { + fn version_sum(&self) -> u64 { + match &self.packet { + PacketType::Litteral(_) => self.version as u64, + PacketType::Operator(op) => op.sub_packets.iter().map(Packet::version_sum).sum(), + } + } +} + +#[derive(PartialEq, Eq, Debug)] +struct LitteralPacket { + value: u64, +} + +#[derive(PartialEq, Eq, Debug)] +struct OperatorPacket { + sub_packets: Vec, +} + +impl std::str::FromStr for Packet { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let s = s.trim(); + let mut bits = BitVec::::new(); + bits.resize(4 * s.len(), false); + + for (i, c) in s.chars().enumerate() { + let bit_index = i * 4; + let digit = c.to_digit(16).context("character wasn't hex digit")?; + bits[bit_index..(bit_index + 4)].store(digit); + } + + bits.as_bitslice().try_into() + } +} + +impl<'bits, Store> TryFrom<&'bits BitSlice> for Packet +where + Store: BitStore, +{ + type Error = anyhow::Error; + + fn try_from(bits: &'bits BitSlice) -> Result { + let version: u8 = bits[0..3].load(); + let type_id: u8 = bits[3..6].load(); + + match type_id { + 4 => { + let mut value = 0; + for i in (6..).step_by(5) { + let val = bits[(i + 1)..(i + 5)].load::(); + value = (value << 4) + val; + + if !bits[i] { + break; + } + } + + Ok(Packet { + version, + type_id, + packet: PacketType::Litteral(LitteralPacket { value }), + }) + } + _ => unimplemented!("Operator packets aren't implemented yet"), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED1: &str = "D2FE28"; + const PROVIDED2: &str = "38006F45291200"; + const PROVIDED3: &str = "EE00D40C823060"; + + const PROVIDED4: &str = "8A004A801A8002F478"; + const PROVIDED5: &str = "620080001611562C8802118E34"; + const PROVIDED6: &str = "C0015000016115A2E0802F182340"; + const PROVIDED7: &str = "A0016C880162017C3686B18A3D4780"; + + #[test] + fn part1_provided() { + assert_eq!( + PROVIDED1.parse::().unwrap(), + Packet { + version: 6, + type_id: 4, + packet: PacketType::Litteral(LitteralPacket { value: 2021 }), + } + ); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 3427e05..f281e9a 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -15,3 +15,4 @@ pub mod day12; pub mod day13; pub mod day14; pub mod day15; +pub mod day16; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 4dcd949..524f73b 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -17,6 +17,7 @@ use aoc2021::day12; use aoc2021::day13; use aoc2021::day14; use aoc2021::day15; +use aoc2021::day16; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -35,6 +36,7 @@ fn main() -> Result<()> { day13::run, day14::run, day15::run, + day16::run, ]; aoc::run(days)