|
| 1 | +//! # Trick Shot |
| 2 | +//! |
| 3 | +//! Although this problem is easy to brute force, we can apply some reasoning and simplify both parts. |
| 4 | +//! |
| 5 | +//! ## Part One |
| 6 | +//! Part one can be solved analytically. Movement upwards in the positive y direction is symmetrical. |
| 7 | +//! For example launching a probe at a y-velocity of 5 initially, |
| 8 | +//! would result in a speed and y-position: |
| 9 | +//! |
| 10 | +//! ``` |
| 11 | +//! Time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 |
| 12 | +//! Speed: 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7 |
| 13 | +//! Y-Position: 0, 5, 9, 12, 14, 15, 15, 14, 12, 9, 5, 0, -6 |
| 14 | +//! ``` |
| 15 | +//! |
| 16 | +//! The maximum y velocity is reached when we *just* touch the target area on the way down at the |
| 17 | +//! bottom y-coordinate. For the example above, if the bottom y coordinate was -6 then the maximum |
| 18 | +//! initial upwards velocity is one less, our starting velocity of 5. |
| 19 | +//! |
| 20 | +//! The maximum height is `5 + 4 + 3 + 2 + 1`, which is the sum from 1 to n given by the formula for |
| 21 | +//! triangular numbers [`(n * (n + 1) / 2`](https://en.wikipedia.org/wiki/Triangular_number#Formula). |
| 22 | +//! |
| 23 | +//! ## Part Two |
| 24 | +//! A brute force solution would check every possible combination of `x` and `y` for a total |
| 25 | +//! complexity of `O(xy)`. By thinking in terms of time `t` instead and applying a dynamic |
| 26 | +//! programming solution we can instead solve in a complexity of `O(x + y)`by treating `x` and `y` |
| 27 | +//! independently. |
| 28 | +//! |
| 29 | +//! We create 2 `vecs`. The first `new` counts how many x-velocity values enter the target area at |
| 30 | +//! time `t` for the first time, only considering horizontal movement. The second `continuing` |
| 31 | +//! counts how many are still in the target area at time `t`. |
| 32 | +//! |
| 33 | +//! For example using the sample `target area: x=20..30, y=-10..-5` gives a progression: |
| 34 | +//! ``` |
| 35 | +//! X-Velocity : 6 |
| 36 | +//! Time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 |
| 37 | +//! New: 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 38 | +//! Continuing: 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |
| 39 | +//! |
| 40 | +//! X-Velocity : 7 |
| 41 | +//! Time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 |
| 42 | +//! New: 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 43 | +//! Continuing: 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 |
| 44 | +//! |
| 45 | +//! X-Velocity : 8 |
| 46 | +//! Time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 |
| 47 | +//! New: 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 48 | +//! Continuing: 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 |
| 49 | +//! |
| 50 | +//! ... |
| 51 | +//! |
| 52 | +//! X-Velocity : 30 |
| 53 | +//! Time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 |
| 54 | +//! New: 0, 11, 5, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 55 | +//! Continuing: 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 |
| 56 | +//! ``` |
| 57 | +//! |
| 58 | +//! Then for each y velocity value we find the time when it enters the target area. The first time |
| 59 | +//! this happens we add *both* `new` and `continuing` to the total. For subsequent times while we're |
| 60 | +//! still in the target area we add only the `new` values, as the `continuing` are trajectories |
| 61 | +//! that we've already considered. For example for an initial y-velocity of 0: |
| 62 | +//! ``` |
| 63 | +//! Time: 0, 1, 2, 3, 4 |
| 64 | +//! Speed: 0, -1, -2, -3, -4 |
| 65 | +//! Y-Position: 0, -1, -3, -6, -10 |
| 66 | +//! Total: 0, 0, 0, 3 + 1, 5 |
| 67 | +//! ``` |
| 68 | +//! |
| 69 | +//! Summing this for all y-velocity values gives the desired result. |
1 | 70 | use crate::util::iter::*;
|
2 | 71 | use crate::util::parse::*;
|
3 | 72 |
|
|
0 commit comments