97 lines
2.5 KiB
Rust
97 lines
2.5 KiB
Rust
#![feature(iterator_try_collect)]
|
|
|
|
use std::fs;
|
|
use std::io::{self, BufRead};
|
|
use std::ops::RangeInclusive;
|
|
use std::str::FromStr;
|
|
|
|
#[derive(Debug)]
|
|
struct WorkRange(RangeInclusive<u32>);
|
|
|
|
impl WorkRange {
|
|
#[allow(dead_code)]
|
|
fn init(start: u32, end: u32) -> Self {
|
|
WorkRange(start..=end)
|
|
}
|
|
|
|
fn fully_contains(&self, other: &Self) -> bool {
|
|
self.0.contains(other.0.start()) && self.0.contains(other.0.end())
|
|
}
|
|
|
|
fn overlaps(&self, other: &Self) -> bool {
|
|
self.0.contains(other.0.start())
|
|
|| self.0.contains(other.0.end())
|
|
|| other.0.contains(self.0.start())
|
|
|| other.0.contains(self.0.end())
|
|
}
|
|
}
|
|
|
|
impl FromStr for WorkRange {
|
|
type Err = <u32 as FromStr>::Err;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let spl: Vec<u32> = s.split('-').map(|n| n.parse()).try_collect()?;
|
|
Ok(WorkRange(spl[0]..=spl[1]))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct ElfPair(WorkRange, WorkRange);
|
|
|
|
impl FromStr for ElfPair {
|
|
type Err = <WorkRange as FromStr>::Err;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let spl: Vec<&str> = s.split(',').collect();
|
|
Ok(ElfPair(spl[0].parse()?, spl[1].parse()?))
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let filename = "etc/p04.txt";
|
|
let file = fs::File::open(filename).expect("Can't open file");
|
|
let reader = io::BufReader::new(file);
|
|
|
|
println!("PART ONE ---------------");
|
|
let pairs: Vec<ElfPair> = reader
|
|
.lines()
|
|
.flat_map(|l| l.expect("Expect valid line").parse())
|
|
.collect();
|
|
|
|
part1(&pairs);
|
|
|
|
println!("\n PART TWO ---------------");
|
|
part2(&pairs);
|
|
}
|
|
|
|
fn part1(pairs: &[ElfPair]) {
|
|
let sum = pairs
|
|
.iter()
|
|
.filter(|ElfPair(l, r)| l.fully_contains(r) || r.fully_contains(l))
|
|
.count();
|
|
println!("num containing: {}", sum);
|
|
}
|
|
|
|
fn part2(pairs: &[ElfPair]) {
|
|
let sum = pairs
|
|
.iter()
|
|
.filter(|ElfPair(l, r)| l.overlaps(r) || r.overlaps(l))
|
|
.count();
|
|
println!("num overlapping: {}", sum);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn range_overlaps() {
|
|
assert!(!WorkRange::init(2, 4).overlaps(&WorkRange::init(6, 8)));
|
|
assert!(!WorkRange::init(2, 3).overlaps(&WorkRange::init(4, 5)));
|
|
assert!(WorkRange::init(5, 7).overlaps(&WorkRange::init(7, 9)));
|
|
assert!(WorkRange::init(2, 8).overlaps(&WorkRange::init(3, 7)));
|
|
assert!(WorkRange::init(6, 6).overlaps(&WorkRange::init(4, 6)));
|
|
assert!(WorkRange::init(2, 6).overlaps(&WorkRange::init(4, 8)));
|
|
}
|
|
}
|