summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2022-01-11 19:13:07 +0100
committerReiner Herrmann <reiner@reiner-h.de>2022-01-11 19:13:07 +0100
commitf9f7f88ab7a8da3bb165f06a94e5e19c160e6609 (patch)
treefeee62b82b4d0722daec0b7d0a1dde3be33ddf9a
parentc4c7c9922ba0c9771908ef3fa15dd5d763cba5e8 (diff)
-rw-r--r--src/bin/day17.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/bin/day17.rs b/src/bin/day17.rs
new file mode 100644
index 0000000..78c2e9e
--- /dev/null
+++ b/src/bin/day17.rs
@@ -0,0 +1,104 @@
+fn main() {
+ let (x1, x2) = (269, 292);
+ let (y1, y2) = (-68, -44);
+ println!("17a: {}", highest_y(x1, x2, y1, y2));
+ println!("17b: {}", count_velocities(x1, x2, y1, y2));
+}
+
+fn hit_target_y(velocity: i64, y1: i64, y2: i64, steps: i64) -> bool {
+ let mut pos = 0;
+ let mut velocity = velocity;
+
+ /* steps already done until 0 is reached again */
+ let initial_steps = velocity * 2 + 1;
+
+ for _ in initial_steps .. steps {
+ velocity += 1;
+ pos -= velocity;
+ }
+
+ pos >= y1 && pos <= y2
+}
+
+fn hit_target_x(velocity: i64, x1: i64, x2: i64, steps: i64) -> bool {
+ let mut pos = 0;
+ let mut velocity = velocity;
+
+ for _ in 0 .. steps {
+ pos += velocity;
+ velocity -= 1;
+ velocity = std::cmp::max(0, velocity);
+ }
+
+ pos >= x1 && pos <= x2
+}
+
+fn peak_y(velocity: i64) -> i64 {
+ velocity * (velocity + 1) / 2
+}
+
+fn highest_y(x1: i64, x2: i64, y1: i64, y2: i64) -> i64 {
+ let mut max = 0;
+ for vel_x in 1 .. 1000 {
+ for vel_y in 0 .. 1000 {
+ for steps in 1 .. 150 {
+ if hit_target_x(vel_x, x1, x2, steps) && hit_target_y(vel_y, y1, y2, steps) {
+ max = std::cmp::max(max, peak_y(vel_y));
+ break;
+ }
+ }
+ }
+ }
+ max
+}
+
+fn count_velocities(x1: i64, x2: i64, y1: i64, y2: i64) -> i64 {
+ let mut count = 0;
+ for vel_x in 1 .. 1000 {
+ for vel_y in -1000 .. 1000 {
+ for steps in 1 .. 150 {
+ if hit_target_x(vel_x, x1, x2, steps) && hit_target_y(vel_y, y1, y2, steps) {
+ count += 1;
+ break;
+ }
+ }
+ }
+ }
+ count
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test() {
+ let (x1, x2) = (20, 30);
+ let (y1, y2) = (-10, -5);
+
+ assert!(!hit_target_x(7, x1, x2, 3));
+ assert!(hit_target_x(7, x1, x2, 4));
+ assert!(hit_target_x(7, x1, x2, 5));
+ assert!(hit_target_x(7, x1, x2, 6));
+ assert!(hit_target_x(7, x1, x2, 7));
+
+ assert!(!hit_target_y(2, y1, y2, 6));
+ assert!(hit_target_y(2, y1, y2, 7));
+ assert!(!hit_target_y(2, y1, y2, 8));
+
+ assert!(!hit_target_x(6, x1, x2, 4));
+ assert!(hit_target_x(6, x1, x2, 5));
+ assert!(hit_target_x(6, x1, x2, 6));
+ assert!(hit_target_x(6, x1, x2, 7));
+ assert!(hit_target_x(6, x1, x2, 8));
+ assert!(hit_target_x(6, x1, x2, 9));
+ assert!(hit_target_x(6, x1, x2, 10));
+
+ assert!(!hit_target_y(3, y1, y2, 8));
+ assert!(hit_target_y(3, y1, y2, 9));
+ assert!(!hit_target_y(3, y1, y2, 10));
+
+ assert_eq!(highest_y(x1, x2, y1, y2), 45);
+ assert_eq!(count_velocities(x1, x2, y1, y2), 112);
+ }
+}