advent_of_code/year2017/
day22.rs1use crate::input::Input;
2use std::collections::HashMap;
3use std::collections::hash_map::Entry;
4
5#[derive(Copy, Clone, Eq, PartialEq)]
6enum NodeFlag {
7 Weakened,
8 Infected,
9 Flagged,
10}
11
12const fn turn(direction: (i32, i32), right: bool) -> (i32, i32) {
13 if right {
14 (-direction.1, direction.0)
15 } else {
16 (direction.1, -direction.0)
17 }
18}
19
20const fn reverse(direction: (i32, i32)) -> (i32, i32) {
21 (-direction.0, -direction.1)
22}
23
24pub fn solve(input: &Input) -> Result<u32, String> {
25 let mut map = HashMap::new();
26
27 let mut cols = -1;
28 let mut rows = -1;
29 for (line_idx, line) in input.text.lines().enumerate() {
30 rows += 1;
31 for (char_idx, char) in line.chars().enumerate() {
32 if rows == 0 {
33 cols += 1;
34 }
35 if char == '#' {
36 map.insert((char_idx as i32, line_idx as i32), NodeFlag::Infected);
37 }
38 }
39 }
40
41 let mut carrier_position = (cols / 2 + cols % 2, rows / 2 + rows % 2);
42 let mut carrier_direction = (0, -1);
43 let mut bursts_causing_infection = 0;
44 for _burst in 0..input.part_values(10_000, 10_000_000) {
45 match map.entry(carrier_position) {
46 Entry::Vacant(entry) => {
47 carrier_direction = turn(carrier_direction, false);
48
49 if input.is_part_one() {
50 bursts_causing_infection += 1;
52 entry.insert(NodeFlag::Infected);
53 } else {
54 entry.insert(NodeFlag::Weakened);
56 }
57 }
58 Entry::Occupied(mut entry) => {
59 match entry.get() {
60 NodeFlag::Weakened => {
61 bursts_causing_infection += 1;
63 entry.insert(NodeFlag::Infected);
64 }
65 NodeFlag::Infected => {
66 carrier_direction = turn(carrier_direction, true);
67
68 if input.is_part_one() {
69 entry.remove();
71 } else {
72 entry.insert(NodeFlag::Flagged);
74 }
75 }
76 NodeFlag::Flagged => {
77 carrier_direction = reverse(carrier_direction);
78
79 entry.remove();
81 }
82 }
83 }
84 }
85
86 carrier_position = (
87 carrier_position.0 + carrier_direction.0,
88 carrier_position.1 + carrier_direction.1,
89 );
90 }
91
92 Ok(bursts_causing_infection)
93}
94
95#[test]
96pub fn tests() {
97 let real_input = include_str!("day22_input.txt");
98 test_part_one!(real_input => 5246);
99 test_part_two!(real_input => 2_512_059);
100}