From 4cff7e84015032a67764e4b1c27851f49da03f78 Mon Sep 17 00:00:00 2001 From: Reiner Herrmann Date: Fri, 3 Dec 2021 18:40:49 +0100 Subject: day3 --- src/bin/day3.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/bin/day3.rs (limited to 'src/bin/day3.rs') diff --git a/src/bin/day3.rs b/src/bin/day3.rs new file mode 100644 index 0000000..cb442ed --- /dev/null +++ b/src/bin/day3.rs @@ -0,0 +1,109 @@ +fn main() { + let input = advent::read_lines(3); + println!("3a: {}", power_consumption(&input)); + println!("3b: {}", life_support_rating(&input)); +} + + +fn power_consumption>(input: &[T]) -> u32 { + let bits = count_ones(input); + let gamma = rate(&bits, input.len(), true); + let epsilon = rate(&bits, input.len(), false); + + gamma * epsilon +} + +fn count_ones_at_pos>(input: &[T], pos: usize) -> usize { + input.iter() + .filter(|&x| x.as_ref().chars().nth(pos).unwrap() == '1') + .count() +} + +fn count_ones>(input: &[T]) -> Vec { + input[0].as_ref() + .chars() + .enumerate() + .map(|(i, _)| count_ones_at_pos(input, i)) + .collect() +} + +fn rate(bits: &[usize], max_count: usize, gamma: bool) -> u32 { + let mut result = 0; + let max_count = max_count; + + for count in bits.iter() { + result <<= 1; + if gamma && 2 * count > max_count { + result += 1; + } + if !gamma && 2 * count < max_count { + result += 1; + } + } + result +} + +fn life_support_rating>(input: &[T]) -> usize { + let oxygen = oxygen_rating(input); + let co2 = co2_rating(input); + + oxygen * co2 +} + +fn co2_rating>(input: &[T]) -> usize { + rating(input, false) +} + +fn oxygen_rating>(input: &[T]) -> usize { + rating(input, true) +} + +fn rating>(input: &[T], oxygen: bool) -> usize { + let mut numbers = vec!["0"; input.len()]; + for (i, number) in input.iter().enumerate() { + numbers[i] = number.as_ref(); + } + + let len = numbers[0].len(); + for i in 0 .. len { + let ones = count_ones_at_pos(&numbers, i); + let keep = if (oxygen && 2 * ones >= numbers.len()) || (!oxygen && 2 * ones < numbers.len()) { + '1' + } else { + '0' + }; + numbers = numbers.iter() + .filter(|&x| x.chars().nth(i).unwrap() == keep) + .copied() + .collect(); + if numbers.len() == 1 { + break; + } + } + usize::from_str_radix(numbers[0], 2).unwrap() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + "00100", + "11110", + "10110", + "10111", + "10101", + "01111", + "00111", + "11100", + "10000", + "11001", + "00010", + "01010", + ]; + assert_eq!(power_consumption(&input), 198); + assert_eq!(life_support_rating(&input), 230); + } +} -- cgit v1.2.3