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 if 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 }
17 None
18}
19
20pub fn solve(input: &Input) -> Result<u32, String> {
21 let mut particles = Vec::new();
22
23 for (line_idx, line) in input.text.lines().enumerate() {
24 let on_error = || format!("Line {}: Invalid format", line_idx + 1);
25
26 let mut parts = line.split(", ");
27 let position_part =
28 parse_vector(parts.next().ok_or_else(on_error)?).ok_or_else(on_error)?;
29 let speed_part = parse_vector(parts.next().ok_or_else(on_error)?).ok_or_else(on_error)?;
30 let acceleration_part =
31 parse_vector(parts.next().ok_or_else(on_error)?).ok_or_else(on_error)?;
32
33 particles.push((position_part, speed_part, acceleration_part));
34 }
35
36 for _ in 0..500 {
37 particles = particles
38 .iter()
39 .filter_map(|particle| {
40 if input.is_part_two()
41 && particles
42 .iter()
43 .filter(|other_particle| other_particle.0 == particle.0)
44 .count()
45 > 1
46 {
47 None
48 } else {
49 let new_speed = (
50 particle.1 .0 + particle.2 .0,
51 particle.1 .1 + particle.2 .1,
52 particle.1 .2 + particle.2 .2,
53 );
54 let new_position = (
55 particle.0 .0 + new_speed.0,
56 particle.0 .1 + new_speed.1,
57 particle.0 .2 + new_speed.2,
58 );
59 let new_acceleration = particle.2;
60 Some((new_position, new_speed, new_acceleration))
61 }
62 })
63 .collect();
64 }
65
66 if input.is_part_one() {
67 Ok(particles
68 .iter()
69 .enumerate()
70 .fold((0, i32::MAX), |acc, (idx, particle)| {
71 let dist = particle.0 .0.abs() + particle.0 .1.abs() + particle.0 .2.abs();
72 if dist < acc.1 {
73 (idx, dist)
74 } else {
75 acc
76 }
77 })
78 .0 as u32)
79 } else {
80 Ok(particles.len() as u32)
81 }
82}
83
84#[test]
85pub fn tests() {
86 use crate::input::{test_part_one, test_part_two};
87
88 let real_input = include_str!("day20_input.txt");
89 test_part_one!(real_input => 91);
90 test_part_two!(real_input => 567);
91}