diff options
-rw-r--r-- | 2024/02/rust/src/main.rs | 37 |
1 files changed, 12 insertions, 25 deletions
diff --git a/2024/02/rust/src/main.rs b/2024/02/rust/src/main.rs index 620fe8b..2007837 100644 --- a/2024/02/rust/src/main.rs +++ b/2024/02/rust/src/main.rs @@ -1,3 +1,5 @@ +#![feature(iter_map_windows)] + use std::io; fn main() { @@ -12,35 +14,20 @@ fn main() { .collect::<Result<Vec<_>, _>>() .unwrap(); - let silver: usize = input.iter().map(self::safe).flatten().count(); - let gold: u64 = 0; + let silver: usize = input.iter().filter(|&xs| all_safe(xs)).count(); + let gold: usize = input.iter().filter(|&xs| drop_safe(xs)).count(); println!("silver: {silver}"); println!("gold: {gold}"); } -#[derive(Debug, PartialEq)] -enum Dir { - Asc, - Desc, +fn all_safe(xs: &Vec<i64>) -> bool { + let mut diffs = xs.iter().map_windows(|&[x, y]| y - x).peekable(); + let dir = diffs.peek().unwrap_or(&1).signum(); + diffs.all(|d| (1..=3).contains(&d.abs()) && d.signum() == dir) } -fn safe(xs: &Vec<i64>) -> Option<Dir> { - let mut dirs = xs - .iter() - .zip(xs.iter().skip(1)) - .map(|(x, y)| y - x) - .map(|d| match d { - -3..=-1 => Some(Dir::Desc), - 1..=3 => Some(Dir::Asc), - _ => None, - }) - .collect::<Option<Vec<Dir>>>()? - .into_iter(); - - let head = dirs.next().unwrap_or(Dir::Asc); - if dirs.all(|d| d == head) { - Some(head) - } else { - None - } +fn drop_safe(xs: &Vec<i64>) -> bool { + (0..xs.len()) + .map(|idx| xs.split_at(idx)) + .any(|(left, right)| all_safe(&[left, &right[1..]].concat())) } |