1use crate::util::iter::*;
3use crate::util::parse::*;
4use crate::util::point::*;
5
6type Input = (String, i32);
7
8pub fn parse(input: &str) -> Input {
9 let (mut points, velocity): (Vec<_>, Vec<_>) = input
10 .iter_signed::<i32>()
11 .chunk::<4>()
12 .map(|[x, y, dx, dy]| (Point::new(x, y), Point::new(dx, dy)))
13 .unzip();
14
15 let up = velocity.iter().position(|v| v.y < 0).unwrap();
17 let down = velocity.iter().position(|v| v.y > 0).unwrap();
18
19 let p = (points[up].y - points[down].y).abs();
21 let v = (velocity[up].y - velocity[down].y).abs();
22 let mut time = (p - 10) / v;
23
24 tick(&mut points, &velocity, time);
26
27 let mut area = size(&points);
30
31 while area > 620 {
32 tick(&mut points, &velocity, 1);
33 area = size(&points);
34 time += 1;
35 }
36
37 adjust(&mut points);
39
40 let mut grid = ['.'; 620];
42 points.iter().for_each(|p| grid[(62 * p.y + p.x) as usize] = '#');
43
44 let mut message = grid
45 .chunks_exact(62)
46 .map(|chunk| chunk.iter().collect())
47 .collect::<Vec<String>>()
48 .join("\n");
49 message.insert(0, '\n');
50
51 (message, time)
52}
53
54pub fn part1(input: &Input) -> &str {
55 &input.0
56}
57
58pub fn part2(input: &Input) -> i32 {
59 input.1
60}
61
62fn bounding_box(points: &[Point]) -> (i32, i32, i32, i32) {
63 let mut min_x = i32::MAX;
64 let mut max_x = i32::MIN;
65 let mut min_y = i32::MAX;
66 let mut max_y = i32::MIN;
67
68 for p in points {
69 min_x = min_x.min(p.x);
70 max_x = max_x.max(p.x);
71 min_y = min_y.min(p.y);
72 max_y = max_y.max(p.y);
73 }
74
75 (min_x, max_x, min_y, max_y)
76}
77
78fn size(points: &[Point]) -> i32 {
79 let (min_x, max_x, min_y, max_y) = bounding_box(points);
80 (max_x - min_x + 1) * (max_y - min_y + 1)
81}
82
83fn adjust(points: &mut [Point]) {
84 let (min_x, _, min_y, _) = bounding_box(points);
85 let top_left = Point::new(min_x, min_y);
86 points.iter_mut().for_each(|p| *p -= top_left);
87}
88
89fn tick(points: &mut [Point], velocity: &[Point], time: i32) {
90 points.iter_mut().zip(velocity.iter()).for_each(|(p, v)| {
91 *p += *v * time;
92 });
93}