2022 day4/rust: use range type

This commit is contained in:
Xiretza 2022-12-04 10:24:39 +01:00
parent 8b15158631
commit 1207b26a46

View file

@ -1,4 +1,42 @@
use std::io::{stdin, Read};
#![warn(clippy::pedantic)]
#![feature(is_some_and)]
use std::{
io::{stdin, Read},
ops::{BitAnd, RangeInclusive},
};
/// A range of sections. Always contains at least one element.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct SectionRange {
start: u64,
end: u64,
}
impl TryFrom<RangeInclusive<u64>> for SectionRange {
type Error = ();
fn try_from(range: RangeInclusive<u64>) -> Result<Self, Self::Error> {
let start = *range.start();
let end = *range.end();
if start <= end {
Ok(Self { start, end })
} else {
Err(())
}
}
}
impl BitAnd for SectionRange {
type Output = Option<Self>;
fn bitand(self, other: Self) -> Self::Output {
let start = self.start.max(other.start);
let end = self.end.min(other.end);
Self::try_from(start..=end).ok()
}
}
fn main() {
let mut data = String::new();
@ -10,11 +48,10 @@ fn main() {
let make_range = |s: &str| {
let (start, end) = s.split_once('-').unwrap();
let start: u64 = start.parse().unwrap();
let start = start.parse().unwrap();
let end = end.parse().unwrap();
assert!(start <= end);
start..=end
SectionRange::try_from(start..=end).unwrap()
};
let (left, right) = line.split_once(',').unwrap();
@ -29,17 +66,11 @@ fn main() {
"{}",
pairs
.iter()
.filter(|(l, r)| l.start() == r.start()
|| l.end() == r.end()
|| l.start().cmp(r.start()) != l.end().cmp(r.end()))
.filter(|&&(l, r)| {
(l & r).is_some_and(|intersection| intersection == l || intersection == r)
})
.count()
);
println!(
"{}",
pairs
.iter()
.filter(|(l, r)| l.end() >= r.start() && r.end() >= l.start())
.count()
);
println!("{}", pairs.iter().filter_map(|&(l, r)| l & r).count());
}