use crate::common::interval::Interval; use crate::solvers::Solver; use std::collections::BTreeSet; use std::io::BufRead; pub struct Cafeteria {} impl Solver for Cafeteria { const PUZZLE_INDEX: u8 = 5; const PUZZLE_NAME: &'static str = "Cafeteria"; fn process_data(&self, mut reader: R) -> (u64, u64) { // Builds intervals collection. let mut intervals: BTreeSet = BTreeSet::new(); for line in reader .by_ref() .lines() .map_while(|x| x.ok().filter(|s| !s.is_empty())) { let values: Vec = line.split('-').map_while(|s| s.parse().ok()).collect(); let mut interval = Interval::new(values[0], values[1]); let mut to_delete = Vec::new(); for next in intervals.range(&interval..) { if interval.contains(next.start) || interval.end + 1 == next.start { // New interval overlaps with the "next" interval already in the collection. if interval.end < next.end { interval.end = next.end; } to_delete.push(next.clone()); } else { break; } } let mut do_insert = true; if let Some(prev) = intervals.range(..=&interval).next_back() { if interval.contains(prev.end) || prev.end + 1 == interval.start { // Enlarges new interval to replace the "previous" interval already in the collection. interval.start = prev.start; to_delete.push(prev.clone()); } else if interval.end <= prev.end { do_insert = false; } } for del in to_delete { intervals.remove(&del); } if do_insert { intervals.insert(interval); } } let mut part1 = 0; // Tests values against intervals. for value in reader.lines().map_while(|x| x.ok()?.parse::().ok()) { if intervals.iter().any(|interval| interval.contains(value)) { part1 += 1; } } (part1, intervals.iter().map(|x| x.len()).sum()) } }