-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathd08.rs
More file actions
124 lines (99 loc) · 3.25 KB
/
d08.rs
File metadata and controls
124 lines (99 loc) · 3.25 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
use lazy_static::lazy_static;
use regex::Regex;
use std::collections::HashMap;
use crate::Day;
pub struct Day08 {}
impl Day for Day08 {
fn year(&self) -> u16 {
2023
}
fn day(&self) -> u8 {
8
}
fn part_one(&self) -> String {
let (map, instructions) = parse_input(&self.read_default_input());
let mut steps = 0;
let mut instruction_idx = 0;
let mut current_node = "AAA";
loop {
if current_node == "ZZZ" {
break;
}
let instruction = instructions[instruction_idx];
let (left, right) = map
.get(current_node)
.expect("all nodes should exist on the map");
match instruction {
'L' => current_node = left,
'R' => current_node = right,
_ => unreachable!(),
}
steps += 1;
instruction_idx = (instruction_idx + 1) % instructions.len();
}
steps.to_string()
}
fn part_two(&self) -> String {
let (map, instructions) = parse_input(&self.read_default_input());
let current_nodes = map
.keys()
.filter(|node| node.ends_with('A'))
.collect::<Vec<&String>>();
let mut cycles = vec![0_u64; current_nodes.len()];
for idx in 0..current_nodes.len() {
let mut node = current_nodes[idx];
let mut step = 0;
let mut instruction_idx = 0;
loop {
let instruction = instructions[instruction_idx];
if node.ends_with('Z') && cycles[idx] == 0 {
cycles[idx] = step;
break;
}
let (left, right) = map.get(node).expect("all nodes should exist on the map");
match instruction {
'L' => node = left,
'R' => node = right,
_ => unreachable!(),
}
step += 1;
instruction_idx = (instruction_idx + 1) % instructions.len();
}
}
lcm(&cycles).to_string()
}
}
lazy_static! {
static ref NODES_REGEX: Regex =
Regex::new(r"([A-Z]{3})\s=\s\(([A-Z]{3}),\s([A-Z]{3})\)").expect("failed to compile regex");
}
type Map = HashMap<String, (String, String)>;
fn parse_input(input: &str) -> (Map, Vec<char>) {
let lines = input
.lines()
.map(|line| line.to_string())
.collect::<Vec<String>>();
let instructions = lines[0].chars().collect::<Vec<char>>();
let mut map: Map = Map::new();
for line in lines[2..].iter() {
let captures = NODES_REGEX.captures(line).unwrap();
let node = captures.get(1).unwrap().as_str().to_string();
let left = captures.get(2).unwrap().as_str().to_string();
let right = captures.get(3).unwrap().as_str().to_string();
map.insert(node, (left, right));
}
(map, instructions)
}
fn lcm(values: &[u64]) -> u64 {
values
.iter()
.fold(1, |acc, &item| acc * item / gcd(acc, item))
}
fn gcd(mut left: u64, mut right: u64) -> u64 {
while right != 0 {
let remainder = left % right;
left = right;
right = remainder;
}
left
}