advent_of_code/year2017/
day20.rs1use crate::input::Input;
2
3fn parse_vector(input: &str) -> Option<(i32, i32, i32)> {
5 if input.len() > 3
6 && let Some(stripped) = input[2..]
7 .strip_prefix('<')
8 .and_then(|s| s.strip_suffix('>'))
9 {
10 let mut number_parts = stripped.split(',');
11 let x = number_parts.next()?.parse::<i16>().ok()?;
12 let y = number_parts.next()?.parse::<i16>().ok()?;
13 let z = number_parts.next()?.parse::<i16>().ok()?;
14 return Some((i32::from(x), i32::from(y), i32::from(z)));
15 }
16 None
17}
18
19pub fn solve(input: &Input) -> Result<u32, String> {
20 let mut particles = Vec::new();
21
22 for (line_idx, line) in input.text.lines().enumerate() {
23 let on_error = || format!("Line {}: Invalid format", line_idx + 1);
24
25 let mut parts = line.split(", ");
26 let position_part =
27 parse_vector(parts.next().ok_or_else(on_error)?).ok_or_else(on_error)?;
28 let speed_part = parse_vector(parts.next().ok_or_else(on_error)?).ok_or_else(on_error)?;
29 let acceleration_part =
30 parse_vector(parts.next().ok_or_else(on_error)?).ok_or_else(on_error)?;
31
32 particles.push((position_part, speed_part, acceleration_part));
33 }
34
35 for _ in 0..500 {
36 particles = particles
37 .iter()
38 .filter_map(|particle| {
39 if input.is_part_two()
40 && particles
41 .iter()
42 .filter(|other_particle| other_particle.0 == particle.0)
43 .count()
44 > 1
45 {
46 None
47 } else {
48 let new_speed = (
49 particle.1.0 + particle.2.0,
50 particle.1.1 + particle.2.1,
51 particle.1.2 + particle.2.2,
52 );
53 let new_position = (
54 particle.0.0 + new_speed.0,
55 particle.0.1 + new_speed.1,
56 particle.0.2 + new_speed.2,
57 );
58 let new_acceleration = particle.2;
59 Some((new_position, new_speed, new_acceleration))
60 }
61 })
62 .collect();
63 }
64
65 if input.is_part_one() {
66 Ok(particles
67 .iter()
68 .enumerate()
69 .fold((0, i32::MAX), |acc, (idx, particle)| {
70 let dist = particle.0.0.abs() + particle.0.1.abs() + particle.0.2.abs();
71 if dist < acc.1 { (idx, dist) } else { acc }
72 })
73 .0 as u32)
74 } else {
75 Ok(particles.len() as u32)
76 }
77}
78
79#[test]
80pub fn tests() {
81 let real_input = include_str!("day20_input.txt");
82 test_part_one!(real_input => 91);
83 test_part_two!(real_input => 567);
84}