1use std::collections::HashMap;
2use utils::point::Point3D;
3use utils::prelude::*;
4
5#[derive(Clone, Debug)]
7pub struct Day20 {
8 particles: Vec<Particle>,
9}
10
11#[derive(Clone, Debug)]
12struct Particle {
13 position: Point3D<i64>,
14 velocity: Point3D<i64>,
15 acceleration: Point3D<i64>,
16}
17
18impl Day20 {
19 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
20 let vector = parser::i64()
21 .repeat_n(b',')
22 .map(|[x, y, z]| Point3D::new(x, y, z));
23
24 Ok(Self {
25 particles: vector
26 .with_prefix("p=<")
27 .then(vector.with_prefix(">, v=<"))
28 .then(vector.with_prefix(">, a=<").with_suffix(">"))
29 .map(|(position, velocity, acceleration)| Particle {
30 position,
31 velocity,
32 acceleration,
33 })
34 .parse_lines(input)?,
35 })
36 }
37
38 #[must_use]
39 pub fn part1(&self) -> usize {
40 self.particles
41 .iter()
42 .enumerate()
43 .min_by_key(|&(_, p)| p.position_at_time(1_000_000).manhattan_distance())
44 .unwrap()
45 .0
46 }
47
48 #[must_use]
49 pub fn part2(&self) -> usize {
50 let mut particles = self.particles.clone();
51 let mut destroyed = vec![false; particles.len()];
52
53 let mut positions = HashMap::new();
54 let mut last_destroyed = 0;
55 for t in 0.. {
56 positions.clear();
57
58 for (i, p) in particles.iter_mut().enumerate() {
59 if destroyed[i] {
60 continue;
61 }
62
63 p.tick();
64
65 if let Some(j) = positions.insert(p.position, i) {
66 destroyed[i] = true;
67 destroyed[j] = true;
68 last_destroyed = t;
69 }
70 }
71
72 if last_destroyed <= t - 10 && destroyed.iter().any(|&x| x) {
75 break;
76 }
77 }
78
79 particles.len() - destroyed.iter().filter(|&&p| p).count()
80 }
81}
82
83impl Particle {
84 fn position_at_time(&self, time: u64) -> Point3D<i64> {
85 self.position
86 + (self.velocity * time as i64)
87 + (self.acceleration * (time as i64 * time as i64 / 2))
88 }
89
90 fn tick(&mut self) {
91 self.velocity += self.acceleration;
92 self.position += self.velocity;
93 }
94}
95
96examples!(Day20 -> (usize, usize) [
97 {
98 input: "p=<3,0,0>, v=<2,0,0>, a=<-1,0,0>\n\
99 p=<4,0,0>, v=<0,0,0>, a=<-2,0,0>",
100 part1: 0,
101 },
102 {
103 input: "p=<-6,0,0>, v=<3,0,0>, a=<0,0,0>\n\
104 p=<-4,0,0>, v=<2,0,0>, a=<0,0,0>\n\
105 p=<-2,0,0>, v=<1,0,0>, a=<0,0,0>\n\
106 p=<3,0,0>, v=<-1,0,0>, a=<0,0,0>",
107 part2: 1,
108 },
109]);