-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday_8.rs
111 lines (90 loc) · 3.16 KB
/
day_8.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use std::collections::HashMap;
use crate::common::maths::lcm;
pub fn parse(input_raw: &str) -> Result<(Vec<char>, HashMap<&str, (&str, &str)>), String> {
let mut lines = input_raw.lines();
let instructions = lines.next().unwrap().chars().collect();
lines.next();
let mut network = HashMap::new();
for line in lines {
let mut split = line.split(" = ");
let node = split.next().unwrap();
let mut connections = split
.next()
.unwrap()
.trim_matches(|c| c == '(' || c == ')')
.split(", ");
network.insert(node, (connections.next().unwrap(), connections.next().unwrap()));
}
Ok((instructions, network))
}
pub fn part_one(input: &(Vec<char>, HashMap<&str, (&str, &str)>)) -> Result<u64, String> {
let (instructions, network) = input.clone();
let mut instruction_index = 0;
let mut steps: u64 = 0;
let mut node = "AAA";
while node != "ZZZ" {
let instruction = instructions[instruction_index];
node = match instruction {
'L' => network.get(node).unwrap().0,
'R' => network.get(node).unwrap().1,
_ => return Err(format!("Invalid character '{instruction}' in instructions")),
};
steps += 1;
instruction_index = (instruction_index + 1) % instructions.len();
}
Ok(steps)
}
pub fn part_two(input: &(Vec<char>, HashMap<&str, (&str, &str)>)) -> Result<u64, String> {
let (instructions, network) = input.clone();
let mut nodes: Vec<&str> = network
.keys()
.filter(|key| key.ends_with("A"))
.map(|key| *key)
.collect();
let mut completion_times = vec![];
for node in nodes.iter_mut() {
let mut instruction_index = 0;
let mut steps: u64 = 0;
while !node.ends_with("Z") {
let instruction = instructions[instruction_index];
*node = match instruction {
'L' => network.get(node).unwrap().0,
'R' => network.get(node).unwrap().1,
_ => return Err(format!("Invalid character '{instruction}' in instructions")),
};
steps += 1;
instruction_index = (instruction_index + 1) % instructions.len();
}
completion_times.push(steps);
}
let mut complete_time = 1;
for steps in completion_times {
complete_time = lcm(complete_time, steps);
}
Ok(complete_time)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1_1() {
let example = include_str!("../../examples/day_8_1.txt");
let parsed = parse(example).unwrap();
let solution = part_one(&parsed);
assert_eq!(solution, Ok(2));
}
#[test]
fn test_part1_2() {
let example = include_str!("../../examples/day_8_2.txt");
let parsed = parse(example).unwrap();
let solution = part_one(&parsed);
assert_eq!(solution, Ok(6));
}
#[test]
fn test_part2() {
let example: &str = include_str!("../../examples/day_8_3.txt");
let parsed = parse(example).unwrap();
let solution = part_two(&parsed);
assert_eq!(solution, Ok(6));
}
}