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); } }