Move Cafeteria code into new MultiInterval struct, add FromStr implementation for Interval
This commit is contained in:
@@ -1,74 +1,31 @@
|
||||
use crate::common::interval::Interval;
|
||||
use crate::common::interval::MultiInterval;
|
||||
use crate::solvers::Solver;
|
||||
use std::collections::BTreeSet;
|
||||
use std::io::BufRead;
|
||||
|
||||
pub struct Cafeteria {}
|
||||
|
||||
impl Cafeteria {
|
||||
const INTERVAL_SPLIT_CHAR: char = '-';
|
||||
}
|
||||
|
||||
impl Solver for Cafeteria {
|
||||
const PUZZLE_INDEX: u8 = 5;
|
||||
const PUZZLE_NAME: &'static str = "Cafeteria";
|
||||
|
||||
fn process_data<R: BufRead>(&self, mut reader: R) -> (u64, u64) {
|
||||
// Builds intervals collection.
|
||||
let mut intervals: BTreeSet<Interval> = BTreeSet::new();
|
||||
let mut intervals = MultiInterval::new();
|
||||
for line in reader
|
||||
.by_ref()
|
||||
.lines()
|
||||
.map_while(|x| x.ok().filter(|s| !s.is_empty()))
|
||||
{
|
||||
// TODO: This code should move into new common::interval::MultiInterval struct.
|
||||
let values: Vec<u64> = line
|
||||
.split(Self::INTERVAL_SPLIT_CHAR)
|
||||
.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);
|
||||
}
|
||||
intervals.add(line.parse().unwrap());
|
||||
}
|
||||
|
||||
let mut part1 = 0;
|
||||
// Tests values against intervals.
|
||||
for value in reader.lines().map_while(|x| x.ok()?.parse::<u64>().ok()) {
|
||||
if intervals.iter().any(|interval| interval.contains(value)) {
|
||||
part1 += 1;
|
||||
}
|
||||
}
|
||||
let fresh_count = reader
|
||||
.lines()
|
||||
.map_while(|x| x.ok()?.parse::<u64>().ok())
|
||||
.filter(|&value| intervals.contains(value))
|
||||
.count() as u64;
|
||||
|
||||
(part1, intervals.iter().map(|x| x.len()).sum())
|
||||
(fresh_count, intervals.len())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user