mod lib;
use std::cmp::min;
struct Range{
Start:usize,
End:usize
}
struct Day5Input{
Ranges:Vec<Range>,
Ids:Vec<usize>,
FinishRange: bool
}
fn read(data: &mut Day5Input, line: &str) {
if line.len() == 0{
data.FinishRange = true;
}
else if data.FinishRange {
data.Ids.push(line.parse().unwrap());
}
else{
let (a,b) = line.split_once("-").unwrap();
let (start, end):(usize, usize) = (a.parse().unwrap(), b.parse().unwrap());
data.Ranges.push(Range{Start: start, End: end});
}
}
fn gold(ranges: &Vec<Range>) -> usize{
let mut data = ranges.clone();
data.sort_by(|a,b| a.Start.cmp(&b.Start));
let mut unions:Vec<Range> = Vec::new();
for range in &data{
let mut entry_to_add = Some(Range{Start: range.Start, End: range.End});
for union in & mut unions{
if let Some(ref entry) = entry_to_add{
let (lower, upper) = (in_range(entry.Start, union), in_range(entry.End, union));
if lower && upper{ entry_to_add = None; break; }
else if lower{
*union = Range{Start: min(entry.Start, union.Start), End: std::cmp::max(entry.End, union.End) };
entry_to_add = None;
}
else if upper{
*union = Range{Start: min(entry.Start, union.Start), End: std::cmp::max(entry.End, union.End) };
entry_to_add = None;
}
}
}
if let Some(entry_add) = entry_to_add{
unions.push(entry_add);
}
}
unions.iter().fold(0, |acc, x| acc + 1 + x.End - x.Start)
}
fn in_range(id:usize, range:& Range) -> bool{
range.Start <= id && id <= range.End
}
fn solve(mut data: Day5Input) -> (usize, usize) {
let mut silver = 0;
let mut gold = gold(&data.Ranges);
for id in &data.Ids{
for range in &data.Ranges{
// silver
if in_range(*id, range){
silver+=1;
break;
}
}
}
(silver, gold)
}
fn main() {
let inp: Day5Input = Day5Input {Ranges:Vec::new(), Ids:Vec::new(), FinishRange: false };
println!("{:?}", lib::read_then_write::<Day5Input>(read, solve, inp));
}