From 1b632cfb8fa153655ff3b322ebbcfd761d4db7f4 Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Sat, 4 Dec 2021 16:30:36 +0100 Subject: First working day3 part 2 implementation. It sucks. --- src/day3.rs | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/day3.rs (limited to 'src/day3.rs') diff --git a/src/day3.rs b/src/day3.rs new file mode 100644 index 0000000..5c17ebd --- /dev/null +++ b/src/day3.rs @@ -0,0 +1,125 @@ +use aoc_runner_derive::*; +use dyn_clone::{clone_trait_object, DynClone}; + +#[aoc_generator(day3)] +pub fn input_generator<'c>(input : &'c str) -> (Vec,usize){ + (input + .lines() + .map(|l| l.chars().rev() + .enumerate() + .fold(0, |count, (index,character)| match character { + '1' => { count + (1 << index)} + _ => { count } + } + ) + ).collect() + , input.lines().map(|l| l.len()).max().unwrap_or(1)) +} + +#[aoc(day3, part1)] +pub fn solve_part1((input,max_len) : &(Vec,usize)) -> usize { + let gamma_rate : usize= (0..*max_len).map(|index| + (index, input.iter().filter(|&&number| number & (1 << index) != 0).count() * 2 / input.len()) + ).map(|(bit, is_one)| is_one << bit).sum(); + let mask = (1 << max_len) - 1; + let epsilon_rate = !gamma_rate & mask; + gamma_rate * epsilon_rate +} + +trait ClonableIterator: Iterator + DynClone {} +impl ClonableIterator for I {} +clone_trait_object!( ClonableIterator); + +fn get_most_or_least_common_bit_by_comparison<'a, T, U>(iterator : T , bit_from_right : usize, comparison : &U) -> bool + where T : Iterator, + U : Fn(usize,usize)->bool +{ + let (ones, zeros) = iterator.fold((0,0), |(ones, zeros), value| if value & (1 < bool { + (record & most_common_bit_mask) == target +} + +fn find_wanted_rating<'a, T,U>(iterator : T, max_len : usize, comparison : U) -> Option + where T : Iterator+Clone, + U : Fn(usize,usize)->bool +{ + let init : Box> = Box::new(iterator); + let result = (0..max_len).rev().fold(init,|iterator, bit_from_right| { + let mask = 1 << bit_from_right; + let target_bit_value = if get_most_or_least_common_bit_by_comparison(iterator.clone(),bit_from_right, &comparison) { mask } else { 0 }; + println!("Most common for bit_from_right {} : {}", bit_from_right, target_bit_value); + let filtered = iterator.filter(move |&&value| has_record_most_common_bit(value,mask,target_bit_value)); + let boxed : Box> = Box::new(filtered); + boxed + }); + //the problem is formulated in a way that guarantees at least one result. + result.take(2).fold(None,|x,y| x.xor(Some(*y))) +} + +fn find_oxygen_rating<'a, T>(iterator : T, max_len : usize) -> Option + where T : Iterator+Clone +{ + find_wanted_rating(iterator, max_len, |a,b| a>=b) +} + +fn find_co2_rating<'a,T>(iterator : T, max_len : usize) -> Option + where T : Iterator+Clone +{ + find_wanted_rating(iterator, max_len, |a,b| (a+b == 1 && a>b) || (a+b !=1 && a, usize)) -> Option { + let oxygen_rating = find_oxygen_rating(input.iter(),*max_len); + oxygen_rating.and_then(|oxygen_rating| { + find_co2_rating(input.iter(), *max_len).map(|co2_rating| co2_rating * oxygen_rating) + }) +} + +#[cfg(test)] +mod day3_tests{ + use super::*; + + fn get_day3_string_testdata() -> &'static str { + "00100\n11110\n10110\n10111\n10101\n01111\n00111\n11100\n10000\n11001\n00010\n01010" + } + + fn get_day3_processed_testdata() -> (Vec, usize) { + (vec![0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001, 0b00010, 0b01010], 5) + } + + #[test] + fn test_generator() { + assert_eq!(input_generator(get_day3_string_testdata()),get_day3_processed_testdata()); + } + + #[test] + fn test_part1() { + let result = solve_part1(&get_day3_processed_testdata()); + assert_eq!(result,198) + } + + #[test] + fn test_find_oxygen_rating() { + let data = get_day3_processed_testdata(); + let result = find_oxygen_rating(data.0.iter(),data.1); + assert_eq!(result, Some(23)) + } + + #[test] + fn test_find_co2_rating() { + let data = get_day3_processed_testdata(); + let result = find_co2_rating(data.0.iter(), data.1); + assert_eq!(result, Some(10)) + } + + #[test] + fn test_part2() { + let result = solve_part2(&get_day3_processed_testdata()); + assert_eq!(result,Some(230)) + } +} -- cgit v1.2.3