use std::cmp::Ordering; use crate::Day; pub struct Day17 { x_min: i32, x_max: i32, y_min: i32, y_max: i32, } impl Day for Day17 { fn init(content: String) -> anyhow::Result { let c = content.split(' ').skip(1).collect::>(); let (x_min, x_max) = c[1][2..(c[1].len() - 1)].split_once("..").unwrap(); let (y_min, y_max) = c[2][2..].split_once("..").unwrap(); Ok(Day17 { x_min: x_min.parse()?, x_max: x_max.parse()?, y_min: y_min.parse()?, y_max: y_max.parse()?, }) } fn part1(&self) -> anyhow::Result { let mut hits = Vec::new(); for dx in 0..=self.x_max { for dy in -100..250 { let points = self.calc((dx, dy)); if self.hits(&points) { hits.push(max_height(&points).unwrap()); } } } Ok(format!("{}", hits.iter().max().unwrap())) } fn part2(&self) -> anyhow::Result { let mut hits = Vec::new(); for dx in 0..=self.x_max { for dy in -100..250 { let points = self.calc((dx, dy)); if self.hits(&points) { hits.push((dx, dy)); } } } Ok(format!("{}", hits.len())) } } impl Day17 { fn hits(&self, points: &[(i32, i32)]) -> bool { points.iter().any(|&(x, y)| x >= self.x_min && x <= self.x_max && y >= self.y_min && y <= self.y_max) } fn calc(&self, initial_velocity: (i32, i32)) -> Vec<(i32, i32)> { let mut steps = vec![(0, 0)]; let mut velocity = initial_velocity; loop { let (x, y) = steps.last().unwrap(); let (x, y) = (x + velocity.0, y + velocity.1); if x > self.x_max || y < self.y_min { break; } steps.push((x, y)); match velocity.0.cmp(&0) { Ordering::Less => velocity.0 += 1, Ordering::Equal => {} Ordering::Greater => velocity.0 -= 1, } velocity.1 -= 1; } steps } } fn max_height(points: &[(i32, i32)]) -> Option { points.iter().map(|&x| x.1).max() } #[cfg(test)] mod tests { use crate::{Day, day_tests}; use crate::day17::Day17; const INPUT: &str = "target area: x=20..30, y=-10..-5"; #[test] fn part1_test() -> anyhow::Result<()> { let d = Day17::init(INPUT.to_string())?; assert_eq!("45", d.part1()?); Ok(()) } #[test] fn part2_test() -> anyhow::Result<()> { let d = Day17::init(INPUT.to_string())?; assert_eq!("112", d.part2()?); Ok(()) } day_tests!(Day17, "17", "4186", "2709"); }