Function advent_of_code_2021::day_17::all_trajectories[−][src]

fn all_trajectories(
    target: ((isize, isize), (isize, isize))
) -> HashSet<(isize, isize)>
Expand description

Calculate an upper and lower bound for x and y co-ordinates, then brute-force iterate through each permutation. There is probably a more efficient solution in working the sets of steps each relevant x and y magnitude will be in the target area and intersecting those, but the brute-force method runs in 1-2ms so is good enough.

The lower bound for y, and the upper bound for x is the trajectory that hits the bottom right of the target area after it’s first step. As noted in highest_point the highest positive y trajectory is -target_y_min - 1 so that on it’s way back down it will hit the x-axis, then the gravity will adjust the speed downwards 1 so that it hits target_y_min next. The lowest x needs to be large enough that it reaches target_x_min before decaying to a delta of 0.

so:

x (x + 1)                               | max x distance for starting x is
---------   >= target_x_min             | triangular number for x
    2                                   |
                                        |
x (x + 1)   >= target_x_min * 2         | multiply both sides by 2
                                        |
x² + x      >= target_x_min * 2         | re-arrange
                                        |
x² + 2x + 1 >  target_x_min * 2         | x is >= 0, so adding x + 1  
                                        | is still > RHS
                                        |
(x + 1)²    >  target_x_min * 2         | re-arrange, (x + 1)(x + 1) ===
                                        | x² + 2x + 1
                                        |
                /----------------       |
x + 1       > \/ target_x_min * 2       | square root both sides
                                        |
                /----------------       |
x           > \/ target_x_min * 2  - 1  | -1 both sides