Day8 Rust
This commit is contained in:
1
day8/rust/.gitignore
vendored
Normal file
1
day8/rust/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
target
|
||||
7
day8/rust/Cargo.lock
generated
Normal file
7
day8/rust/Cargo.lock
generated
Normal 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
8
day8/rust/Cargo.toml
Normal 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
182
day8/rust/src/main.rs
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user