Advent of Code 2023 - Day 24Never Tell Me The Odds
| Problem statement | Source code | Tags: Geometry Mathematics
← Previous Back to year Index Next →
Each hailstone is a parametric equation. If we are given x1, y1, z1 @ vx1, vy1, vz1, then the position of the hailstone at time t is given by:
p 1 ( t ) = p 1 ( 0 ) + t v 1 \mathbf{p}_1(t) = \mathbf{p}_1(0) + t \mathbf{v}_1 p 1 ( t ) = p 1 ( 0 ) + t v 1
where p 1 ( 0 ) = ( x 1 , y 1 , z 1 ) ⊤ \mathbf{p}_1(0) = (x_1, y_1, z_1)^\top p 1 ( 0 ) = ( x 1 , y 1 , z 1 ) ⊤ and v 1 = ( v x 1 , v y 1 , v z 1 ) ⊤ \mathbf{v}_1 = (vx_1, vy_1, vz_1)^\top v 1 = ( v x 1 , v y 1 , v z 1 ) ⊤ .
In part 1 we only care about 2D, so instead p 1 ( 0 ) = ( x 1 , y 1 ) ⊤ \mathbf{p}_1(0) = (x_1, y_1)^\top p 1 ( 0 ) = ( x 1 , y 1 ) ⊤ and v 1 = ( v x 1 , v y 1 ) ⊤ \mathbf{v}_1 = (vx_1, vy_1)^\top v 1 = ( v x 1 , v y 1 ) ⊤ . To find the intersection of two hailstone paths (perhaps at different times) is to find the solution to:
p 1 ( t 1 ) = p 2 ( t 2 ) p 1 ( 0 ) + t 1 v 1 = p 2 ( 0 ) + t 2 v 2 [ v x 1 − v x 2 v y 1 − v y 2 ] [ t 1 t 2 ] = [ x 2 − x 1 y 2 − y 1 ] \begin{aligned}
\mathbf{p}_1(t_1) &= \mathbf{p}_2(t_2)\\
\mathbf{p}_1(0) + t_1 \mathbf{v}_1 &= \mathbf{p}_2(0) + t_2 \mathbf{v}_2\\
\begin{bmatrix}vx_1 & -vx_2 \\ vy_1 & -vy_2\end{bmatrix} \begin{bmatrix}t_1 \\ t_2\end{bmatrix} &= \begin{bmatrix}x_2 - x_1 \\ y_2 - y_1\end{bmatrix}
\end{aligned} p 1 ( t 1 ) p 1 ( 0 ) + t 1 v 1 [ v x 1 v y 1 − v x 2 − v y 2 ] [ t 1 t 2 ] = p 2 ( t 2 ) = p 2 ( 0 ) + t 2 v 2 = [ x 2 − x 1 y 2 − y 1 ]
This linear system can be directly solved in R gmp with solve.bigz. The system may not have a solution if the two paths are parallel; we additionally require t 1 , t 2 ≥ 0 t_1, t_2 \geq 0 t 1 , t 2 ≥ 0 for the solution to be valid. The intersection point can be found by plugging t 1 t_1 t 1 into p 1 ( t ) \mathbf{p}_1(t) p 1 ( t ) .
After obtaining the intersection point, we can easily test if it's in the test area.
Now coordinates are 3D. We need some p ( 0 ) \mathbf{p}(0) p ( 0 ) and v \mathbf{v} v , such that for every i i i ,
p i ( 0 ) + t i v i = p ( 0 ) + t i v p i ( 0 ) + t i ( v i − v ) = p ( 0 ) \begin{aligned}
\mathbf{p}_i(0) + t_i \mathbf{v}_i = \mathbf{p}(0) + t_i \mathbf{v}\\
\mathbf{p}_i(0) + t_i (\mathbf{v}_i - \mathbf{v}) = \mathbf{p}(0)
\end{aligned} p i ( 0 ) + t i v i = p ( 0 ) + t i v p i ( 0 ) + t i ( v i − v ) = p ( 0 )
If we take two trails, i i i and j j j , we can eliminate p ( 0 ) \mathbf{p}(0) p ( 0 ) :
p i ( 0 ) + t i ( v i − v ) = p j ( 0 ) + t j ( v j − v ) t i ( v i − v ) − t j ( v j − v ) = p j ( 0 ) − p i ( 0 ) \begin{aligned}
\mathbf{p}_i(0) + t_i (\mathbf{v}_i - \mathbf{v}) &= \mathbf{p}_j(0) + t_j (\mathbf{v}_j - \mathbf{v})\\
t_i (\mathbf{v}_i - \mathbf{v}) - t_j (\mathbf{v}_j - \mathbf{v}) &= \mathbf{p}_j(0) - \mathbf{p}_i(0)
\end{aligned} p i ( 0 ) + t i ( v i − v ) t i ( v i − v ) − t j ( v j − v ) = p j ( 0 ) + t j ( v j − v ) = p j ( 0 ) − p i ( 0 )
This means that p j ( 0 ) − p i ( 0 ) \mathbf{p}_j(0) - \mathbf{p}_i(0) p j ( 0 ) − p i ( 0 ) can be expressed as a linear combination of v i − v \mathbf{v}_i - \mathbf{v} v i − v and v j − v \mathbf{v}_j - \mathbf{v} v j − v , i.e., p j ( 0 ) − p i ( 0 ) \mathbf{p}_j(0) - \mathbf{p}_i(0) p j ( 0 ) − p i