advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git
commit c6a137276db40b5d7989702f7541aa95bfb29bfd
parent f432e372d1ce4ab00e3de4ff340e810c2e3e0ee1
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date:   Fri, 17 Dec 2021 18:38:37 -0600

Add 2021 day 17

Diffstat:
A2021/day17/input.txt | 1+
A2021/day17/main.rs | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/2021/day17/input.txt b/2021/day17/input.txt
@@ -0,0 +1 @@
+target area: x=155..215, y=-132..-72
diff --git a/2021/day17/main.rs b/2021/day17/main.rs
@@ -0,0 +1,59 @@
+fn main() {
+    let x_range = (155, 215);
+    let y_range = (-132, -72);
+    // 8646
+    println!("Part 1: {}", part_1(x_range, y_range));
+    // 5945
+    println!("Part 2: {}", part_2(x_range, y_range));
+}
+
+fn fire(v: (i32, i32), x_range: (i32, i32), y_range: (i32, i32)) -> Option<()> {
+    let mut x = 0;
+    let mut y = 0;
+    let (mut x_v, mut y_v) = v;
+    while x <= x_range.1 && y >= y_range.0 {
+        x += x_v;
+        y += y_v;
+        y_v -= 1;
+        x_v -= x_v.signum();
+        if x >= x_range.0 && x <= x_range.1 && y >= y_range.0 && y <= y_range.1 {
+            return Some(());
+        }
+    }
+    None
+}
+
+fn part_1(x_range: (i32, i32), y_range: (i32, i32)) -> i32 {
+    // x_v * (x_v + 1) / 2 is final x pos
+    let x_v_min = ((2.0 * x_range.0 as f64 + 1.0).sqrt() - 1.0).floor() as i32;
+    let x_v_max = x_range.1;
+    // no point firing downwards
+    let y_v_min = 0;
+    // when crossing y=0 again, the speed is same as initial speed, just pointing downwards.
+    let y_v_max = y_range.0.abs();
+    let mut y_max = 0;
+    for x_v in x_v_min..=x_v_max {
+        for y_v in y_v_min..=y_v_max {
+            if let Some(_) = fire((x_v, y_v), x_range, y_range) {
+                y_max = y_max.max(y_v * (y_v + 1) / 2);
+            }
+        }
+    }
+    y_max
+}
+
+fn part_2(x_range: (i32, i32), y_range: (i32, i32)) -> i32 {
+    let x_v_min = ((2.0 * x_range.0 as f64 + 1.0).sqrt() - 1.0).floor() as i32;
+    let x_v_max = x_range.1;
+    let y_v_min = y_range.0;
+    let y_v_max = y_range.0.abs();
+    let mut arrive_count = 0;
+    for x_v in x_v_min..=x_v_max {
+        for y_v in y_v_min..=y_v_max {
+            if let Some(_) = fire((x_v, y_v), x_range, y_range) {
+                arrive_count += 1;
+            }
+        }
+    }
+    arrive_count
+}