use aoc_runner_derive::{aoc, aoc_generator}; type Data = Vec; fn make_histogram(input: &[u16]) -> Vec<(usize, i64)> { let counts: &mut [Option] = &mut [None; 64]; input.iter().for_each(|val| { for (n, count) in counts.iter_mut().enumerate().take(12) { let v = count.get_or_insert(0); if ((val >> n) & 1) == 1 { *v += 1; } else { *v -= 1; } } }); counts.reverse(); counts .iter() .enumerate() .filter_map(|(a, b)| b.map(|b| (a, b))) .collect::>() } #[aoc_generator(day03)] pub fn input_generator(input: &str) -> Vec { input .lines() .map(|l| u16::from_str_radix(l, 2).unwrap()) .collect() } #[derive(Debug)] enum Mode { MostCommon, LeastCommon, } fn tree_filter(data: &[u16], mut pos: usize, mode: Mode) -> u16 { let (zero, one) = data .iter() .partition::, _>(|&v| ((v >> pos) & 1) == 0); if data.is_empty() { panic!("Uh Oh!"); } if data.len() == 1 { return data[0]; } pos=pos.wrapping_sub(1); if zero.len() == one.len() { match mode { Mode::MostCommon => tree_filter(&one, pos, mode), Mode::LeastCommon => tree_filter(&zero, pos, mode), } } else { let mut srt = vec![zero, one]; srt.sort_by_key(|v| v.len()); match mode { Mode::MostCommon => tree_filter(&srt[1], pos, mode), Mode::LeastCommon => tree_filter(&srt[0], pos, mode), } } } const ASCII_ZERO: u8 = 0x30; #[aoc(day03, part1)] // 1997414 pub fn solve_part1(input: &Data) -> usize { let counts = make_histogram(input); let (gamma, epsilon): (String, String) = counts .iter() .map(|(_, v)| { ( (ASCII_ZERO + (*v >= 0) as u8) as char, (ASCII_ZERO + (*v < 0) as u8) as char, ) }) .unzip(); let gamma = usize::from_str_radix(&gamma, 2).unwrap(); let epsilon = usize::from_str_radix(&epsilon, 2).unwrap(); gamma * epsilon } #[aoc(day03, part2)] // 1032597 pub fn solve_part2(input: &[u16]) -> usize { // let input: Vec = input.iter().for_each(|v| v[0]).collect(); let a = tree_filter(input, 11, Mode::MostCommon) as usize; let b = tree_filter(input, 11, Mode::LeastCommon) as usize; a * b }