aoc_24/src/day2/mod.rs
2024-12-17 00:15:53 +05:30

135 lines
2.8 KiB
Rust

use std::str::SplitWhitespace;
pub fn run() {
let input = include_str!("input");
let safe = input
.lines()
.map(SplitWhitespaceNumbers::new)
.filter_map(|mut line| is_safe(&mut line))
.count();
println!("1. {}", safe); // 510
let safe_corrected = input
.lines()
.map(ExpandedSplitWhitespaceNumbers::new)
.filter_map(|mut line| is_safe_corrected(&mut line))
.count();
println!("2. {}", safe_corrected); // 553
}
struct SplitWhitespaceNumbers<'a> {
line: SplitWhitespace<'a>,
}
struct ExpandedSplitWhitespaceNumbers {
line: Vec<i32>,
skip_index: Option<i32>,
}
impl ExpandedSplitWhitespaceNumbers {
fn new(line: &str) -> Self {
let line = SplitWhitespaceNumbers::new(line).collect();
Self {
line,
skip_index: None,
}
}
}
impl Iterator for ExpandedSplitWhitespaceNumbers {
type Item = Vec<i32>;
fn next(&mut self) -> Option<Self::Item> {
let mut v = self.line.clone();
if let Some(index) = self.skip_index {
if index as usize >= v.len() {
return None;
}
v.remove(index as usize);
self.skip_index = Some(index + 1);
} else {
self.skip_index = Some(0);
}
Some(v)
}
}
impl<'a> SplitWhitespaceNumbers<'a> {
fn new(line: &'a str) -> Self {
SplitWhitespaceNumbers {
line: line.split_whitespace(),
}
}
}
impl<'a> Iterator for SplitWhitespaceNumbers<'a> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
let c = self.line.next();
if c.is_none() {
return None;
}
let c = c.unwrap();
let num = c.parse::<i32>().unwrap();
Some(num)
}
}
fn is_safe_corrected<T>(numbers: &mut T) -> Option<bool>
where
T: Iterator<Item = Vec<i32>>,
{
for variant in numbers.into_iter() {
if is_safe(&mut variant.into_iter()).is_some() {
return Some(true);
}
}
None
}
fn is_safe<T>(numbers: &mut T) -> Option<bool>
where
T: Iterator<Item = i32>,
{
let first = numbers.next().unwrap();
let second = numbers.next().unwrap();
let incr = if second - first > 0 { 1 } else { -1 };
let mut cur = second;
if !is_safe_interval(first, second, incr) {
return None;
}
loop {
let next = numbers.next();
if next.is_none() {
break;
}
let next = next.unwrap();
if !is_safe_interval(cur, next, incr) {
return None;
}
cur = next;
}
Some(true)
}
fn is_safe_interval(first: i32, second: i32, incr: i32) -> bool {
let diff = second - first;
if diff == 0 {
return false;
}
let norm = diff * incr;
norm > 0 && norm < 4
}