diff --git a/2021/day3/day3_rs/Cargo.toml b/2021/day3/day3_rs/Cargo.toml new file mode 100644 index 0000000..bc126b8 --- /dev/null +++ b/2021/day3/day3_rs/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day3_rs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2021/day3/day3_rs/src/main.rs b/2021/day3/day3_rs/src/main.rs new file mode 100644 index 0000000..76496a8 --- /dev/null +++ b/2021/day3/day3_rs/src/main.rs @@ -0,0 +1,58 @@ +#![warn(clippy::pedantic)] +use std::io::{stdin, BufRead}; + +fn find_rating(num_bits: usize, mut range: &[usize], keep_most_common_bit: bool) -> usize { + for idx in (0..num_bits).rev() { + if range.len() == 1 { + break; + } + + let nth_bit = |x| x >> idx & 1; + let partition_point = range.iter().position(|&n| nth_bit(n) == 1).unwrap(); + let center_bit = nth_bit(range[range.len() / 2]); + + let keep_first_half = if keep_most_common_bit { + center_bit == 0 + } else { + center_bit == 1 + }; + + if keep_first_half { + range = &range[..partition_point]; + } else { + range = &range[partition_point..]; + } + } + + range[0] +} + +fn main() { + let lines: Vec<_> = stdin().lock().lines().map(Result::unwrap).collect(); + + let num_bits = lines[0].len(); + + let gamma: usize = (0..num_bits) + .map(|i| { + lines + .iter() + .filter(|line| line.chars().nth(i).unwrap() == '1') + .count() + }) + .map(|n| if n > lines.len() / 2 { 1 } else { 0 }) + .reduce(|accum, bit| accum << 1 | bit) + .unwrap(); + let sigma = !gamma & ((1 << num_bits) - 1); + + println!("{}", gamma * sigma); + + let mut numbers: Vec<_> = lines + .iter() + .map(|n| usize::from_str_radix(n, 2).unwrap()) + .collect(); + numbers.sort_unstable(); + + let oxygen = find_rating(num_bits, &numbers, true); + let co2 = find_rating(num_bits, &numbers, false); + println!("{}", oxygen * co2); +}