use hashbrown::HashMap; use itertools::Itertools; use md5::{Digest, Md5}; pub fn part_one(input: &str) -> Option { let key = input.trim().as_bytes(); let mut hasher = Md5::new(); let mut count = 0; let mut res = String::new(); for x in 0..std::u64::MAX { hasher.update(key); hasher.update(x.to_string().as_bytes()); let output = hasher.finalize_reset(); if output.starts_with(&[0, 0]) && output[2] <= 0x0F { count += 1; res.push_str(&format!("{:02x}", output[2])[1..]); } if count == 8 { break; } } Some(res) } pub fn part_two(input: &str) -> Option { let key = input.trim().as_bytes(); let mut hasher = Md5::new(); let mut res = HashMap::new(); for x in 0..std::u64::MAX { hasher.update(key); hasher.update(x.to_string().as_bytes()); let output = hasher.finalize_reset(); if output.starts_with(&[0, 0]) && output[2] <= 0x0F { let (p, c) = format!("{:02x}{:02x}", output[2], output[3])[1..3] .chars() .next_tuple() .unwrap(); if ('0'..='7').contains(&p) && !res.contains_key(&p) { res.insert(p, c); } } if res.len() == 8 { break; } } Some( res.iter() .sorted_by(|a, b| a.0.cmp(b.0)) .map(|(_, v)| v) .collect(), ) } fn main() { let input = &aoc::read_file("inputs", 5); aoc::solve!(1, part_one, input); aoc::solve!(2, part_two, input); } #[cfg(test)] mod tests { use super::*; #[test] fn test_part_one() { let input = aoc::read_file("examples", 5); assert_eq!(part_one(&input), Some("18f47a30".to_string())); } #[test] fn test_part_two() { let input = aoc::read_file("examples", 5); assert_eq!(part_two(&input), Some("05ace8e3".to_string())); } }