From 1d57712afaf6ca222c4d65ef1366be0020afb6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=A9=20Cassiop=C3=A9e=20Gauthier?= Date: Fri, 17 Dec 2021 14:38:38 -0500 Subject: [PATCH] Day 17 --- Cargo.toml | 4 ++ src/day17.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 src/day17.rs diff --git a/Cargo.toml b/Cargo.toml index 9bf8bc5..1438192 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,3 +66,7 @@ path = "src/day15.rs" [[bin]] name = "day16" path = "src/day16.rs" + +[[bin]] +name = "day17" +path = "src/day17.rs" diff --git a/src/day17.rs b/src/day17.rs new file mode 100644 index 0000000..eeaff33 --- /dev/null +++ b/src/day17.rs @@ -0,0 +1,111 @@ +use std::ops::RangeInclusive; + +#[derive(Clone, Debug)] +struct Area { + x: RangeInclusive, + y: RangeInclusive, +} + +impl Area { + fn contains(&self, x: i32, y: i32) -> bool { + self.x.contains(&x) && self.y.contains(&y) + } +} + +fn simulate(area: &Area, dx: i32, dy: i32) -> Option { + let mut hit = false; + let mut max_y = 0; + for step in 0..1000 { + let x = if step < dx { + // General solution for $ x_{t+1} - x_t = -t - dx + 1 $. + ((2 * dx + 1) * step - step * step) / 2 + } else { + // Special case when $ x_{t+1} - x_t = 0 $ is reached. + (dx * dx + dx) / 2 + }; + let y = ((2 * dy + 1) * step - step * step) / 2; + + if y > max_y { + max_y = y; + } + + if area.contains(x, y) { + hit = true; + } + + if y < *area.y.start() { + break; + } + } + + hit.then(|| max_y) +} + +fn find_max_y(area: Area) -> i32 { + let mut max_y = 0; + for dx in 1..=*area.x.end() { + for dy in 1..1000 { + if let Some(y) = simulate(&area, dx, dy) { + if y > max_y { + max_y = y; + } + } + } + } + max_y +} + +fn count_hits(area: Area) -> i32 { + let mut counter = 0; + for dx in 1..=*area.x.end() { + for dy in *area.y.start()..1000 { + if simulate(&area, dx, dy).is_some() { + counter += 1; + } + } + } + counter +} + +fn main() { + let area = Area { + x: (179..=201), + y: (-109..=-63), + }; + println!("solution {}", find_max_y(area.clone())); + println!("solution {}", count_hits(area)); +} + +#[test] +fn test_find_max_y() { + assert_eq!( + find_max_y(Area { + x: (20..=30), + y: (-10..=-5) + }), + 45 + ); +} + +#[test] +fn test_simulate() { + let area = Area { + x: (20..=30), + y: (-10..=-5), + }; + assert_eq!(simulate(&area, 7, 2), Some(3)); + assert_eq!(simulate(&area, 6, 3), Some(6)); + assert_eq!(simulate(&area, 17, -4), None); + assert_eq!(simulate(&area, 6, 9), Some(45)); +} + +#[test] +fn test_count_hits() { + assert_eq!( + count_hits(Area { + x: (20..=30), + y: (-10..=-5) + }), + 112 + ); +}