87 lines
2.6 KiB
Rust
87 lines
2.6 KiB
Rust
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<io::BufReader<File>>) {
|
|
// Builds intervals collection.
|
|
let mut intervals: BTreeSet<Interval> = BTreeSet::new();
|
|
for line in lines
|
|
.by_ref()
|
|
.map_while(|x| x.ok().filter(|s| !s.is_empty()))
|
|
{
|
|
let values: Vec<u64> = 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::<u64>().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 }
|
|
}
|
|
}
|