diff --git a/Cargo.lock b/Cargo.lock index c4f166d..4424af8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,8 +8,10 @@ version = "0.1.0" dependencies = [ "aoc-runner", "aoc-runner-derive", + "bitvec", "itertools", "num", + "radix_fmt", "yap", ] @@ -48,12 +50,30 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "bitvec" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "funty" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" + [[package]] name = "itertools" version = "0.10.1" @@ -163,6 +183,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" + +[[package]] +name = "radix_fmt" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426" + [[package]] name = "ryu" version = "1.0.6" @@ -208,12 +240,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "wyz" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" +dependencies = [ + "tap", +] + [[package]] name = "yap" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index f3c8792..844f7e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" [dependencies] aoc-runner = "0.3.0" aoc-runner-derive = "0.3.0" +bitvec = "0.22.3" itertools = "0.10.1" num = "0.4.0" +radix_fmt = "1.0.0" yap = "0.7.1" diff --git a/src/day_03.rs b/src/day_03.rs index 92af10a..f05d4b4 100644 --- a/src/day_03.rs +++ b/src/day_03.rs @@ -1,80 +1,88 @@ use aoc_runner_derive::{aoc, aoc_generator}; +use bitvec::prelude::*; + +type Mbv = BitVec; + #[aoc_generator(day3)] -pub fn parse_diagnostics(input: &str) -> Vec { - input.lines().map(String::from).collect() +pub fn parse_diagnostics(input: &str) -> Vec { + input + .lines() + .map(|line| { + let length = line.len(); + let mut element = usize::from_str_radix(line, 2).unwrap(); + element <<= usize::BITS - length as u32; + let mut vec: Mbv = Mbv::from_element(element); + vec.truncate(length); + vec + }) + .collect() } #[aoc(day3, part1)] -pub fn calculate_power_consumption(input: &[String]) -> usize { - let gamma_factor = most_common_bit_string(input); - let epsilon_factor = invert_binary_string(&gamma_factor); - let gamma_factor = usize::from_str_radix(&gamma_factor, 2).unwrap(); - let epsilon_factor = usize::from_str_radix(&epsilon_factor, 2).unwrap(); +pub fn calculate_power_consumption(input: &[Mbv]) -> usize { + let gamma_factor = most_common_bit_vec(input); + let epsilon_factor = invert_bit_vec(&gamma_factor); + let gamma_factor = bit_vec_to_usize(&gamma_factor); + let epsilon_factor = bit_vec_to_usize(&epsilon_factor); gamma_factor * epsilon_factor } -pub fn most_common_bit(input: &[String], pos: usize) -> char { - let mut count = 0; - for val in input { - if val.get(pos..=pos).unwrap() == "1" { - count += 1 - } - } - if count * 2 >= input.len() { - '1' - } else { - '0' - } +pub fn most_common_bit(input: &[Mbv], pos: usize) -> bool { + let count = input.iter().filter(|vec| *vec.get(pos).unwrap()).count(); + count * 2 >= input.len() } -pub fn most_common_bit_string(input: &[String]) -> String { - let mut ret_val = String::new(); +pub fn most_common_bit_vec(input: &[Mbv]) -> Mbv { + let mut ret_val = Mbv::new(); for i in 0..input[0].len() { ret_val.push(most_common_bit(input, i)) } ret_val } -pub fn invert_binary_string(val: &str) -> String { - let mut ret_val = String::new(); - for charactor in val.chars() { - match charactor { - '0' => ret_val.push('1'), - '1' => ret_val.push('0'), - _ => (), +pub fn invert_bit_vec(val: &Mbv) -> Mbv { + val.iter().map(|val| !*val).collect() +} + +pub fn bit_vec_to_usize(val: &Mbv) -> usize { + let mut ret_val = 0; + for bit in val { + ret_val <<= 1; + if *bit { + ret_val += 1; } } ret_val } -pub fn get_oxygen_generator_rating(input: &[String]) -> usize { - get_recursive_prefix_match(input, false) +pub fn get_oxygen_generator_rating(input: &[Mbv]) -> usize { + bit_vec_to_usize(&get_recursive_prefix_match(input, false)) } -pub fn get_co2_scrubber_rating(input: &[String]) -> usize { - get_recursive_prefix_match(input, true) +pub fn get_co2_scrubber_rating(input: &[Mbv]) -> usize { + bit_vec_to_usize(&get_recursive_prefix_match(input, true)) } -pub fn get_recursive_prefix_match(input: &[String], invert: bool) -> usize { - let mut input = Vec::from(input); +pub fn get_recursive_prefix_match(input: &[Mbv], invert: bool) -> Mbv { + let mut input: Vec = input.to_vec(); for i in 0..input[0].len() { if input.len() > 1 { - let mut target = String::from(most_common_bit(&input, i)); + let mut target = most_common_bit(&input, i); if invert { - target = invert_binary_string(&target); + target = !target; } - input.retain(|val| val.get(i..=i) == Some(&target)); + input.retain(|val| val.get(i).unwrap() == target); } else { break; } } assert_eq!(input.len(), 1); - usize::from_str_radix(&input[0], 2).unwrap() + input[0].clone() } #[aoc(day3, part2)] -pub fn calculate_life_support_rating(input: &[String]) -> usize { +pub fn calculate_life_support_rating(input: &[Mbv]) -> usize { get_oxygen_generator_rating(input) * get_co2_scrubber_rating(input) }