76 lines
1.7 KiB
Rust
76 lines
1.7 KiB
Rust
//! Day 4: Camp Cleanup
|
|
|
|
use std::ops::RangeInclusive;
|
|
|
|
fn get_ranges(input: Vec<String>) -> Vec<(RangeInclusive<u32>, RangeInclusive<u32>)> {
|
|
// 31-31,32-40
|
|
input
|
|
.into_iter()
|
|
.map(|line| {
|
|
let (r1, r2) = line.split_once(',').unwrap();
|
|
(parse_range(r1), parse_range(r2))
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn parse_range(s: &str) -> RangeInclusive<u32> {
|
|
let (a, b) = s.split_once('-').unwrap();
|
|
RangeInclusive::new(a.parse().unwrap(), b.parse().unwrap())
|
|
}
|
|
|
|
pub fn part1(input: Vec<String>) -> String {
|
|
let ranges = get_ranges(input);
|
|
|
|
ranges
|
|
.iter()
|
|
.filter(|(a, b)| {
|
|
(b.start() >= a.start() && b.end() <= a.end())
|
|
|| (a.start() >= b.start() && a.end() <= b.end())
|
|
})
|
|
.count()
|
|
.to_string()
|
|
}
|
|
|
|
pub fn part2(input: Vec<String>) -> String {
|
|
let ranges = get_ranges(input);
|
|
|
|
ranges
|
|
.iter()
|
|
.filter(|(a, b)| {
|
|
a.contains(b.start())
|
|
|| a.contains(b.end())
|
|
|| b.contains(a.start())
|
|
|| b.contains(a.end())
|
|
})
|
|
.count()
|
|
.to_string()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn t_example() {
|
|
let input = vec![
|
|
"2-4,6-8".to_owned(),
|
|
"2-3,4-5".to_owned(),
|
|
"5-7,7-9".to_owned(),
|
|
"2-8,3-7".to_owned(),
|
|
"6-6,4-6".to_owned(),
|
|
"2-6,4-8".to_owned(),
|
|
];
|
|
assert_eq!(part1(input.clone()), "2");
|
|
assert_eq!(part2(input), "4");
|
|
}
|
|
|
|
#[test]
|
|
fn t_part1() {
|
|
assert_eq!(part1(crate::read_input(4)), "556");
|
|
}
|
|
|
|
#[test]
|
|
fn t_part2() {
|
|
assert_eq!(part2(crate::read_input(4)), "876");
|
|
}
|
|
}
|