advent_of_code/year2022/
day09.rs1use crate::input::Input;
2
3pub fn solve(input: &Input) -> Result<usize, String> {
4 let snake_len = input.part_values(2, 10);
5 let mut snake = vec![(0_i32, 0_i32); snake_len];
6 let mut visited = Vec::with_capacity(input.text.len());
7 visited.push((0_i32, 0_i32));
8
9 for line in input.text.lines().filter(|line| line.len() > 2) {
10 let direction = line.as_bytes()[0];
11 let steps = i32::from(
12 line[2..]
13 .parse::<u8>()
14 .map_err(|_| "Not an integer for steps".to_string())?,
15 );
16
17 match direction {
18 b'U' => snake[0].1 -= steps,
19 b'R' => snake[0].0 += steps,
20 b'D' => snake[0].1 += steps,
21 _ => snake[0].0 -= steps,
22 };
23
24 for _ in 0..steps {
25 for i in 1..snake_len {
26 if snake[i - 1].0.abs_diff(snake[i].0) > 1
27 || snake[i - 1].1.abs_diff(snake[i].1) > 1
28 {
29 snake[i].0 += (snake[i - 1].0 - snake[i].0).signum();
30 snake[i].1 += (snake[i - 1].1 - snake[i].1).signum();
31 if i + 1 == snake_len {
32 visited.push(snake[i]);
33 }
34 }
35 }
36 }
37 }
38
39 visited.sort_unstable();
40 Ok(visited.windows(2).filter(|w| w[0] != w[1]).count() + 1)
41}
42
43#[test]
44pub fn tests() {
45 let test_input = "R 4\nU 4\nL 3\nD 1\nR 4\nD 1\nL 5\nR 2";
46 test_part_one!(test_input => 13);
47 test_part_two!(test_input => 1);
48
49 let test_input = "R 5\nU 8\nL 8\nD 3\nR 17\nD 10\nL 25\nU 20";
50 test_part_two!(test_input => 36);
51
52 let real_input = include_str!("day09_input.txt");
53 test_part_one!(real_input => 6081);
54 test_part_two!(real_input => 2487);
55}