Skip to content

Commit f136588

Browse files
committed
Document year 2021 day 16-17
1 parent e30366b commit f136588

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

src/year2021/day16.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
//! Packet Decoder
2+
//!
3+
//! [`BitStream`] is the key to making this problem tractable. It works like an iterator, allowing
4+
//! us to consume an arbitrary number of bits from the input and convert this to a number.
5+
//!
6+
//! It works by maintaining an internal `u64` buffer. If the requested number of bits is larger than
7+
//! the buffer's current size then additional bits are added to the buffer 4 at a time from each
8+
//! hexadecimal digit of the input data.
9+
//!
10+
//! Additionally it keeps track of the total number of bits consumed so far. This is needed when
11+
//! parsing packets that use the total length in bits to determine sub-packets.
12+
//!
13+
//! The decoded packet data is stored as a tree-like struct allowing recursive solutions to part 1
14+
//! and part 2 to reuse the same decoded input.
115
use std::slice::Iter;
216

317
struct BitStream<'a> {

src/year2021/day17.rs

+69
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,72 @@
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.
170
use crate::util::iter::*;
271
use crate::util::parse::*;
372

0 commit comments

Comments
 (0)