diff --git a/src/bin/05.rs b/src/bin/05.rs new file mode 100644 index 0000000..f470db1 --- /dev/null +++ b/src/bin/05.rs @@ -0,0 +1,90 @@ +use aoc::*; +use itertools::Itertools; + +const INPUT: &str = include_str!("../../input/05"); + +fn main() { + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); +} + +#[test] +fn example() { + assert_example!(part1, "05-test", 3); + assert_example!(part2, "05-test", 14); + assert_eq!(part2("1-10\n5-6\n\n"), 10); + assert_eq!(part2("1-10\n8-20\n\n"), 20); + assert_eq!(part2("1-1\n2-2\n3-3\n\n"), 3); + assert_eq!(part2("4-4\n\n"), 1); +} + +fn part1(input: &str) -> usize { + let (ranges, ingredients) = parse_input(input); + ingredients + .into_iter() + .filter(|&i| ranges.contains(i)) + .count() +} + +fn part2(input: &str) -> i64 { + let (ranges, _) = parse_input(input); + + let mut sum = 0; + let mut lower_bound = ranges.ranges.first().unwrap().from; + + for range in ranges.ranges { + let from = range.from.max(lower_bound); + if range.to < from { + continue; + } + + let count = range.to - from + 1; + sum += count; + + lower_bound = range.to + 1; + } + + sum +} + +fn parse_input(input: &str) -> (Ranges, Vec) { + let (ranges, ingredients) = input.split_once("\n\n").unwrap(); + + let ranges = Ranges::parse(ranges); + let ingredients = ingredients.lines().map(|l| l.parse().unwrap()).collect(); + (ranges, ingredients) +} + +struct Ranges { + ranges: Vec, +} + +impl Ranges { + fn parse(input: &str) -> Self { + let mut ranges = input.lines().map(Range::parse).collect_vec(); + ranges.sort_by_key(|r| r.from); + Self { ranges } + } + + fn contains(&self, ingredient: i64) -> bool { + self.ranges.iter().any(|r| r.contains(ingredient)) + } +} + +struct Range { + from: i64, + to: i64, +} + +impl Range { + fn parse(line: &str) -> Self { + let (from, to) = line.split_once('-').unwrap(); + let from = from.parse().unwrap(); + let to = to.parse().unwrap(); + Self { from, to } + } + + fn contains(&self, ingredient: i64) -> bool { + ingredient >= self.from && ingredient <= self.to + } +}