Day8 Rust

This commit is contained in:
dobiadi
2023-12-09 19:59:34 +01:00
parent 55ae7103b8
commit d462e9eea0
4 changed files with 198 additions and 0 deletions

1
day8/rust/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
target

7
day8/rust/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "rust"
version = "0.1.0"

8
day8/rust/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

182
day8/rust/src/main.rs Normal file
View File

@@ -0,0 +1,182 @@
enum Direction {
Left,
Right,
}
#[derive(Debug, Clone)]
struct Node {
name: String,
left_name: String,
right_name: String,
left: Option<usize>,
right: Option<usize>,
}
struct History {
node: usize,
idx: usize,
}
#[derive(Debug)]
struct Period {
offset: usize,
period: usize,
z: Vec<usize>,
}
fn main() {
let stdin = std::io::stdin();
let mut first = true;
let mut instructions = Vec::new();
let mut nodes = Vec::new();
for line in stdin.lines() {
let line = line.unwrap();
if line.len() == 0 && first {
first = false;
} else if first {
instructions = line
.chars()
.map(|e| {
return match e {
'L' => Direction::Left,
'R' => Direction::Right,
_ => unreachable!(),
};
})
.collect();
} else {
let (name, paths) = line.split_once("=").unwrap();
let (left, right) = paths.split_once(",").unwrap();
let left: String = left.chars().filter(|e| *e != '(').collect();
let right: String = right.chars().filter(|e| *e != ')').collect();
nodes.push(Node {
name: name.trim().into(),
left_name: left.trim().into(),
right_name: right.trim().into(),
left: None,
right: None,
});
}
}
let tmp = nodes.clone();
for node in &mut nodes {
for (i, candidate) in tmp.iter().enumerate() {
if candidate.name == node.left_name {
node.left = Some(i);
}
}
for (i, candidate) in tmp.iter().enumerate() {
if candidate.name == node.right_name {
node.right = Some(i);
}
}
}
// Find starter
let mut curr = 0;
for (i, node) in nodes.iter().enumerate() {
if node.name == "AAA" {
curr = i;
break;
}
}
let mut part1 = 0;
while nodes[curr].name != "ZZZ" {
if let Direction::Left = instructions[part1 % instructions.len()] {
curr = nodes[curr].left.unwrap();
} else {
curr = nodes[curr].right.unwrap();
}
part1 += 1;
}
println!("{}", part1);
let mut currents = Vec::new();
for (i, node) in nodes.iter().enumerate() {
if node.name.ends_with("A") {
currents.push(i);
}
}
let mut periods = Vec::new();
for i in 0..currents.len() {
let mut step = 0;
let mut found = false;
let mut history = Vec::new();
while !found {
history.push(History {
node: currents[i],
idx: step % instructions.len(),
});
if let Direction::Left = instructions[step % instructions.len()] {
currents[i] = nodes[currents[i]].left.unwrap();
} else {
currents[i] = nodes[currents[i]].right.unwrap();
}
step += 1;
for (j, h) in history.iter().enumerate() {
if h.node == currents[i] && step % instructions.len() == h.idx {
found = true;
let mut z = Vec::new();
for k in j..history.len() {
if nodes[history[k].node].name.ends_with("Z") {
z.push(k - j);
}
}
periods.push(Period {
offset: j,
period: history.len() - j,
z
});
}
}
}
}
let mut part2 = 0;
let mut found = false;
let mut step = periods[0].offset;
while !found {
for z0 in &periods[0].z {
found = true;
part2 = step + *z0;
for period in &periods {
let mut found2 = false;
for z in &period.z {
if (part2 - period.offset) % period.period == *z {
found2 = true;
break;
}
}
if !found2 {
found = false;
break;
}
}
}
step += periods[0].period;
}
println!("{}", part2);
}