use std::io::{BufReader, Read}; use aoc::Day; struct Day2{} impl Day2 { fn part_n(&self, input: BufReader>) -> Vec> { self.read_lines(input) .iter() .map(|l| { l.split_whitespace().map(|c| { c.parse::().unwrap() }) .collect() }) .collect() } fn is_safe(&self, line: &Vec) -> Result { let mut last: Option<&i32> = None; let mut ascending: Option = None; for (index, i) in line.iter().enumerate() { if let Some(l) = last { let abs_diff = l.abs_diff(*i); if abs_diff < 1 || abs_diff > 3 { return Err(index) } if let Some(asc) = ascending { let diff = i - l; if (asc && diff < 0) || (!asc && diff > 0) { return Err(index) } } else { ascending = Some(i > l); } } last = Some(i); } Ok(true) } } impl Day for Day2 { fn example_input(&self) -> &'static str { r#" 7 6 4 2 1 1 2 7 8 9 9 7 6 2 1 1 3 2 4 5 8 6 4 4 1 1 3 6 7 9 "#.trim() } fn example_result_part_1(&self) -> &'static str { "2" } fn example_result_part_2(&self) -> &'static str { "4" } fn part_1(&self, input: BufReader>) -> String { self.part_n(input) .iter() .filter(|&l| self.is_safe(l).unwrap_or(false)) .count() .to_string() } fn part_2(&self, input: BufReader>) -> String { self.part_n(input) .iter() .filter(|&l| { match self.is_safe(l) { Ok(val) => val, Err(_index) => { l .iter() .enumerate() .map(|(index, _)| { let mut copy = l.clone(); copy.remove(index); self.is_safe(©).unwrap_or(false) }) .any(|val| val) }, } }) .count() .to_string() } } fn main() { aoc::main(&Day2 {}); } #[cfg(test)] mod tests { use super::*; #[test] fn test_day2() { aoc::test_day(&Day2 {}); } }