Advent of Code solutions in Rust

refactor: introduce `try_from_iter_exact` utility

+39 -4
+1 -2
aoc_2020/src/day14.rs
··· 63 63 type Err = anyhow::Error; 64 64 65 65 fn from_str(s: &str) -> Result<Self> { 66 - // FIXME: This should use `try_from_iter_exact()` 67 - aoc_utils::array::try_from_iter(s.chars().rev().map(|c| match c { 66 + aoc_utils::array::try_from_iter_exact(s.chars().rev().map(|c| match c { 68 67 'X' => Ok(None), 69 68 '0' => Ok(Some(false)), 70 69 '1' => Ok(Some(true)),
+1 -2
aoc_2025/src/day12.rs
··· 79 79 Ok::<_, ParseIntError>([x.parse()?, y.parse()?]) 80 80 .with_context(|| anyhow!("failed to parse region dimenions {dimensions:?}")) 81 81 })?; 82 - // TODO: add try_from_iter_exact 83 - let presents = aoc_utils::array::try_from_iter(shapes.split_whitespace().map(|s| { 82 + let presents = aoc_utils::array::try_from_iter_exact(shapes.split_whitespace().map(|s| { 84 83 s.parse() 85 84 .with_context(|| anyhow!("failed to parse present count {s:?}")) 86 85 }))?
+37
aoc_utils/src/array.rs
··· 95 95 }) 96 96 } 97 97 98 + pub fn try_from_iter_exact<T, E, const N: usize>( 99 + iter: impl IntoIterator<Item = Result<T, E>>, 100 + ) -> Result<Result<[T; N], Vec<T>>, E> { 101 + let mut n = 0; 102 + let mut fused = iter.into_iter().fuse(); 103 + let array: [_; N] = try_from_fn(|i| { 104 + if let Some(elem) = fused.next() { 105 + n = i + 1; 106 + Ok(MaybeUninit::new(elem?)) 107 + } else { 108 + Ok(MaybeUninit::uninit()) 109 + } 110 + })?; 111 + 112 + Ok(if n != N { 113 + // received fewer elements from the iterator than N 114 + Err(array 115 + .into_iter() 116 + .take(n) 117 + .map(|x| unsafe { x.assume_init() }) 118 + .collect()) 119 + } else if let Some(extra) = fused.next() { 120 + // received at least one more element than expected 121 + let mut vec: Vec<T> = array 122 + .into_iter() 123 + .map(|x| unsafe { x.assume_init() }) 124 + .collect(); 125 + vec.push(extra?); 126 + for extra in fused { 127 + vec.push(extra?); 128 + } 129 + Err(vec) 130 + } else { 131 + Ok(array.map(|x| unsafe { x.assume_init() })) 132 + }) 133 + } 134 + 98 135 pub fn try_map<T, U, E, const N: usize>( 99 136 array: [T; N], 100 137 f: impl FnMut(T) -> Result<U, E>,