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