use crate::prelude::*; pub type O = usize; pub const INPUT: &'static str = "qzyelonm"; fn _solve (extra: u32) -> O { let mut candidates: M> = M::new(); let mut done: Vec = vec![]; for i in 0.. { let s = format!("{INPUT}{i}"); let mut hash = md5::compute(s); let mut repr = format!("{:x}", hash); for _ in 0..extra { hash = md5::compute(repr); repr = format!("{:x}", hash); } let three = repr.chars().tuple_windows().find(|&(a, b, c)| a == b && b == c); if let Some((c, _, _)) = three { if !candidates.is_empty() { let five = repr.chars().tuple_windows().find(|&(a, b, c, d, e)| a == b && a == c && a == d && a == e); if let Some((c, _, _, _, _)) = five { if let Some(candidates) = candidates.get_mut(&c) { let pos = candidates.iter().position(|pos| pos + 1000 > i); if let Some(pos) = pos { done.extend(candidates.drain(pos..)); candidates.clear(); if done.len() >= 100 { // should be pretty solid, but not sure if I can prove this! done.sort(); return done[63]; } } } } } candidates.entry(c).or_default().push(i); } } 0 } fn _silver () -> O { _solve(0) } fn _gold () -> O { _solve(2016) } #[cfg(test)] mod test { use super::*; #[test] fn silver () { let ans = _silver(); assert_eq!(ans, 15168) } #[test] fn gold () { let ans = _gold(); assert_eq!(ans, 20864) } }