day 5
This commit is contained in:
143
src/day5.rs
Normal file
143
src/day5.rs
Normal file
@@ -0,0 +1,143 @@
|
||||
use std::cmp;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct UintInclusiveRange {
|
||||
start: u64,
|
||||
end: u64,
|
||||
}
|
||||
|
||||
impl UintInclusiveRange {
|
||||
fn new(start: u64, end: u64) -> Self {
|
||||
UintInclusiveRange {
|
||||
start: start,
|
||||
end: end,
|
||||
}
|
||||
}
|
||||
|
||||
fn in_range(&self, value: u64) -> bool {
|
||||
value >= self.start && value <= self.end
|
||||
}
|
||||
|
||||
fn overlaps(&self, other: &UintInclusiveRange) -> bool {
|
||||
(self.start >= other.start && self.start <= other.end)
|
||||
|| (self.end >= other.start && self.end <= other.end)
|
||||
|| (self.start <= other.start && self.end >= other.end)
|
||||
|| (self.start >= other.start && self.end <= other.end)
|
||||
}
|
||||
|
||||
fn join(&self, other: &UintInclusiveRange) -> UintInclusiveRange {
|
||||
println!(
|
||||
"Joining {:?} and {:?} into {:?}",
|
||||
self,
|
||||
other,
|
||||
UintInclusiveRange::new(
|
||||
cmp::min(self.start, other.start),
|
||||
cmp::max(self.end, other.end),
|
||||
)
|
||||
);
|
||||
assert!(self.overlaps(&other));
|
||||
UintInclusiveRange::new(
|
||||
cmp::min(self.start, other.start),
|
||||
cmp::max(self.end, other.end),
|
||||
)
|
||||
}
|
||||
|
||||
fn size(self) -> u64 {
|
||||
self.end - self.start + 1
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> (Vec<UintInclusiveRange>, Vec<u64>) {
|
||||
(
|
||||
input
|
||||
.split("\n")
|
||||
.take_while(|x| *x != "")
|
||||
.map(|x| {
|
||||
UintInclusiveRange::new(
|
||||
x.split("-").nth(0).unwrap().parse().unwrap(),
|
||||
x.split("-").nth(1).unwrap().parse().unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<UintInclusiveRange>>(),
|
||||
input
|
||||
.split("\n")
|
||||
.skip_while(|x| *x != "")
|
||||
.filter(|&x| !x.is_empty())
|
||||
.map(|x| x.parse::<u64>().unwrap())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
#[aoc(day5, part1)]
|
||||
pub fn part1(input: &str) -> u64 {
|
||||
let (fresh_ingredients, available_ingredients) = parse_input(input);
|
||||
available_ingredients
|
||||
.iter()
|
||||
.filter(|x| fresh_ingredients.iter().any(|y| y.in_range(**x)))
|
||||
.count() as u64
|
||||
}
|
||||
|
||||
#[aoc(day5, part2)]
|
||||
pub fn part2(input: &str) -> u64 {
|
||||
let (mut fresh_ingredients, _) = parse_input(input);
|
||||
|
||||
let mut joined_ingredients = <Vec<UintInclusiveRange>>::new();
|
||||
|
||||
fresh_ingredients.sort_by(|x, y| x.start.cmp(&y.start));
|
||||
let mut init = UintInclusiveRange::new(0, 0);
|
||||
|
||||
for ingredient in &fresh_ingredients {
|
||||
if ingredient.start <= init.end {
|
||||
init = UintInclusiveRange::new(init.start, init.end.max(ingredient.end));
|
||||
} else {
|
||||
if init.start != 0 && init.end != 0 {
|
||||
joined_ingredients.push(init);
|
||||
}
|
||||
init = UintInclusiveRange::new(ingredient.start, ingredient.end);
|
||||
}
|
||||
}
|
||||
|
||||
joined_ingredients.push(init);
|
||||
|
||||
joined_ingredients.iter().map(|x| x.size()).sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
let test_input = String::from(
|
||||
"3-5
|
||||
10-14
|
||||
16-20
|
||||
12-18
|
||||
|
||||
1
|
||||
5
|
||||
8
|
||||
11
|
||||
17
|
||||
32",
|
||||
);
|
||||
assert_eq!(part1(&test_input), 3)
|
||||
}
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
let test_input = String::from(
|
||||
"3-5
|
||||
10-14
|
||||
16-20
|
||||
12-18
|
||||
|
||||
1
|
||||
5
|
||||
8
|
||||
11
|
||||
17
|
||||
32",
|
||||
);
|
||||
assert_eq!(part2(&test_input), 14)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ extern crate aoc_runner_derive;
|
||||
// pub mod day1;
|
||||
// pub mod day2;
|
||||
// pub mod day3;
|
||||
pub mod day4;
|
||||
// pub mod day4;
|
||||
pub mod day5;
|
||||
|
||||
aoc_lib! { year = 2025 }
|
||||
|
||||
Reference in New Issue
Block a user