From 4729fa062dff30d848a1a5376ca0017163b9d886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Christian=20Gr=C3=BCnhage?= Date: Sat, 4 Dec 2021 11:47:22 +0100 Subject: [PATCH] implement day 3 --- src/day_03.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 108 insertions(+) create mode 100644 src/day_03.rs diff --git a/src/day_03.rs b/src/day_03.rs new file mode 100644 index 0000000..92af10a --- /dev/null +++ b/src/day_03.rs @@ -0,0 +1,107 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +#[aoc_generator(day3)] +pub fn parse_diagnostics(input: &str) -> Vec { + input.lines().map(String::from).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(); + 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_string(input: &[String]) -> String { + let mut ret_val = String::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'), + _ => (), + } + } + ret_val +} + +pub fn get_oxygen_generator_rating(input: &[String]) -> 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_recursive_prefix_match(input: &[String], invert: bool) -> usize { + let mut input = Vec::from(input); + for i in 0..input[0].len() { + if input.len() > 1 { + let mut target = String::from(most_common_bit(&input, i)); + if invert { + target = invert_binary_string(&target); + } + input.retain(|val| val.get(i..=i) == Some(&target)); + } else { + break; + } + } + assert_eq!(input.len(), 1); + usize::from_str_radix(&input[0], 2).unwrap() +} + +#[aoc(day3, part2)] +pub fn calculate_life_support_rating(input: &[String]) -> usize { + get_oxygen_generator_rating(input) * get_co2_scrubber_rating(input) +} + +#[cfg(test)] +mod test { + const EXAMPLE_INPUT: &str = "00100 +11110 +10110 +10111 +10101 +01111 +00111 +11100 +10000 +11001 +00010 +01010"; + + #[test] + fn test_power_consumption_example() { + let result = super::calculate_power_consumption(&super::parse_diagnostics(EXAMPLE_INPUT)); + assert_eq!(result, 198); + } + + #[test] + fn test_life_support_example() { + let result = super::calculate_life_support_rating(&super::parse_diagnostics(EXAMPLE_INPUT)); + assert_eq!(result, 230); + } +} diff --git a/src/lib.rs b/src/lib.rs index 43d3e05..6b0f086 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,5 +2,6 @@ use aoc_runner_derive::aoc_lib; pub mod day_01; pub mod day_02; +pub mod day_03; aoc_lib! { year = 2021 }