83 lines
1.9 KiB
Rust
83 lines
1.9 KiB
Rust
use itertools::Itertools;
|
|
|
|
use crate::common::{Answer, Solution};
|
|
|
|
pub struct Day02;
|
|
|
|
impl Solution for Day02 {
|
|
fn name(&self) -> &'static str {
|
|
"Red-Nosed Reports"
|
|
}
|
|
|
|
fn part_a(&self, input: &str) -> Answer {
|
|
input
|
|
.lines()
|
|
.filter(|l| {
|
|
let nums = l.split_whitespace().map(|n| n.parse::<i32>().unwrap());
|
|
|
|
is_valid(&nums)
|
|
})
|
|
.count()
|
|
.into()
|
|
}
|
|
|
|
fn part_b(&self, input: &str) -> Answer {
|
|
input
|
|
.lines()
|
|
.filter(|l| {
|
|
let nums = l.split_whitespace().map(|n| n.parse::<i32>().unwrap());
|
|
let valid = is_valid(&nums);
|
|
|
|
if !valid {
|
|
let len = nums.clone().count();
|
|
for skip_i in 0..len {
|
|
let new_nums = nums
|
|
.clone()
|
|
.enumerate()
|
|
.filter_map(|(i, n)| (skip_i != i).then_some(n));
|
|
|
|
if is_valid(&new_nums) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
valid
|
|
})
|
|
.count()
|
|
.into()
|
|
}
|
|
}
|
|
|
|
fn is_valid<T: Iterator<Item = i32> + Clone>(nums: &T) -> bool {
|
|
let diffs = nums.clone().tuple_windows().map(|(a, b)| a - b);
|
|
|
|
diffs.clone().all(|d| (-3..=-1).contains(&d)) || diffs.clone().all(|d| (1..=3).contains(&d))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::Day02;
|
|
use crate::common::Solution;
|
|
|
|
use indoc::indoc;
|
|
|
|
const INPUT: &str = indoc! {"
|
|
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
|
|
"};
|
|
|
|
#[test]
|
|
fn part_a() {
|
|
assert_eq!(Day02.part_a(INPUT), 2.into());
|
|
}
|
|
|
|
#[test]
|
|
fn part_b() {
|
|
assert_eq!(Day02.part_b(INPUT), 4.into());
|
|
}
|
|
}
|