use crate::common::interval::Interval; use crate::solvers::Solver; use std::collections::BTreeSet; use std::fs::File; use std::io; pub struct Cafeteria { part1: u64, part2: u64, } impl Solver for Cafeteria { fn get_puzzle_index(&self) -> u8 { 5 } fn get_puzzle_name(&self) -> &str { "Cafeteria" } fn get_input_filename(&self) -> &str { "cafeteria.txt" } fn get_part1(&self) -> u64 { self.part1 } fn get_part2(&self) -> u64 { self.part2 } fn process_data(&mut self, mut lines: io::Lines>) { // Builds intervals collection. let mut intervals: BTreeSet = BTreeSet::new(); for line in lines .by_ref() .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); } } // Tests values against intervals. for value in lines.map_while(|x| x.ok()?.parse::().ok()) { if intervals.iter().any(|interval| interval.contains(value)) { self.part1 += 1; } } self.part2 = intervals.iter().map(|x| x.len()).sum(); } } impl Cafeteria { pub fn new() -> Cafeteria { Cafeteria { part1: 0, part2: 0 } } }