79 lines
2.2 KiB
Rust
79 lines
2.2 KiB
Rust
use std::cmp::Ordering;
|
|
use crate::common::{parse_input, Level};
|
|
|
|
fn task1() {
|
|
let raw_input = include_str!("./input.txt");
|
|
let safe_levels = parse_input(raw_input)
|
|
.into_iter()
|
|
.map(LevelState::from)
|
|
.filter(LevelState::is_all_safe)
|
|
.count();
|
|
println!("The solution to task 1 is {safe_levels}")
|
|
}
|
|
|
|
#[derive(PartialOrd, PartialEq, Debug, Copy, Clone)]
|
|
pub(crate) enum State {
|
|
Increase(usize),
|
|
Decrease(usize),
|
|
Stable,
|
|
}
|
|
|
|
impl State {
|
|
pub(crate) fn from_values(first: usize, second: usize) -> Self {
|
|
match second.cmp(&first) {
|
|
Ordering::Less => Self::Decrease(first.abs_diff(second)),
|
|
Ordering::Greater => Self::Increase(first.abs_diff(second)),
|
|
Ordering::Equal => Self::Stable,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn is_safely_increasing(&self) -> bool {
|
|
matches!(self, State::Increase(1..=3))
|
|
}
|
|
|
|
pub(crate) fn is_safely_decreasing(&self) -> bool {
|
|
matches!(self, State::Decrease(1..=3))
|
|
}
|
|
}
|
|
|
|
pub(crate) struct LevelState(pub(crate) Vec<State>);
|
|
|
|
impl From<Level> for LevelState {
|
|
fn from(level: Level) -> Self {
|
|
let mut previous = None;
|
|
let mut level_state = Vec::with_capacity(level.0.len());
|
|
|
|
for current in level.0 {
|
|
if let Some(previous) = previous {
|
|
level_state.push(State::from_values(previous, current))
|
|
} else {
|
|
level_state.push(State::Stable);
|
|
}
|
|
previous = Some(current);
|
|
}
|
|
Self(level_state)
|
|
}
|
|
}
|
|
|
|
impl LevelState {
|
|
pub(crate) fn is_all_safe(&self) -> bool {
|
|
self.is_all_safely_increasing() || self.is_all_safely_decreasing()
|
|
}
|
|
|
|
fn is_all_safely_increasing(&self) -> bool {
|
|
self.is_all_changing(State::is_safely_increasing)
|
|
}
|
|
|
|
fn is_all_safely_decreasing(&self) -> bool {
|
|
self.is_all_changing(State::is_safely_decreasing)
|
|
}
|
|
|
|
fn is_all_changing(&self, verify: fn(&State) -> bool) -> bool {
|
|
let states = &self.0;
|
|
match &states[..] {
|
|
[State::Stable, tail @ ..] if tail.iter().all(verify) => true,
|
|
[State::Stable] | [] => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
} |