100 lines
3.5 KiB
Rust
100 lines
3.5 KiB
Rust
use nom::{
|
|
bytes::complete::{take, tag},
|
|
character::complete::alphanumeric1,
|
|
sequence::{preceded, separated_pair},
|
|
IResult,
|
|
};
|
|
use std::collections::HashMap;
|
|
use num::integer::lcm;
|
|
|
|
fn parse_mapline(input: &str) -> IResult<&str, (&str, (&str, &str))> {
|
|
let (input, start) = take(3 as usize)(input)?;
|
|
let (input, (left, right)) = preceded(tag(" = ("), separated_pair(alphanumeric1, tag(", "), alphanumeric1))(input)?;
|
|
Ok((input, (start, (left, right))))
|
|
}
|
|
|
|
pub fn part1(input: &str) -> String {
|
|
let mut lines = input.lines();
|
|
let instructions = lines.next().unwrap().chars();
|
|
let map = lines.skip(1).map(|line| {
|
|
parse_mapline(line).unwrap().1
|
|
}).collect::<HashMap<&str, (&str, &str)>>();
|
|
let mut total_steps = 0;
|
|
let mut position = "AAA";
|
|
for _ in 0..100 {
|
|
for instruction in instructions.clone() {
|
|
total_steps += 1;
|
|
let (left, right) = map.get(position).unwrap();
|
|
if instruction == 'L' {
|
|
position = left;
|
|
} else {
|
|
position = right;
|
|
}
|
|
if position == "ZZZ" { return total_steps.to_string(); };
|
|
}
|
|
};
|
|
total_steps.to_string()
|
|
}
|
|
|
|
pub fn part2(input: &str) -> String {
|
|
// let mut lines = input.lines();
|
|
// let instructions = lines.next().unwrap().chars();
|
|
// let map = lines.skip(1).map(|line| {
|
|
// parse_mapline(line).unwrap().1
|
|
// }).collect::<HashMap<&str, (&str, &str)>>();
|
|
// let start_nodes = map.keys().into_iter().filter(|x| x.chars().last().unwrap() == 'A').collect::<Vec<_>>();
|
|
// let mut total_steps = 0_u64;
|
|
// let mut positions = start_nodes;
|
|
// for _ in 0..1000000 {
|
|
// for instruction in instructions.clone() {
|
|
// total_steps += 1;
|
|
// for i in 0..positions.len() {
|
|
// let (left, right) = map.get(positions[i]).unwrap();
|
|
// if instruction == 'L' {
|
|
// positions[i] = &left;
|
|
// } else {
|
|
// positions[i] = &right;
|
|
// }
|
|
// }
|
|
// if positions.iter().all(|x| {x.chars().last().unwrap() == 'Z'}) { return total_steps.to_string(); };
|
|
// }
|
|
// };
|
|
// total_steps.to_string()
|
|
let mut lines = input.lines();
|
|
let instructions = lines.next().unwrap().chars();
|
|
let map = lines.skip(1).map(|line| {
|
|
parse_mapline(line).unwrap().1
|
|
}).collect::<HashMap<&str, (&str, &str)>>();
|
|
let start_nodes = map.keys().into_iter().filter(|x| x.chars().last().unwrap() == 'A').collect::<Vec<_>>();
|
|
let mut solutions = Vec::<u64>::new();
|
|
for ind in 0..start_nodes.len() {
|
|
let mut total_steps = 0;
|
|
let start_node = start_nodes[ind];
|
|
let mut position = *start_node;
|
|
for _ in 0..100000 {
|
|
for instruction in instructions.clone() {
|
|
total_steps += 1;
|
|
let (left, right) = map.get(position).unwrap();
|
|
if instruction == 'L' {
|
|
position = left;
|
|
} else {
|
|
position = right;
|
|
}
|
|
if position.chars().last().unwrap() == 'Z' { break; };
|
|
}
|
|
if position.chars().last().unwrap() == 'Z' { break; };
|
|
};
|
|
solutions.push(total_steps);
|
|
}
|
|
println!("{:?}", &solutions);
|
|
let first = solutions[0];
|
|
solutions.into_iter().skip(1).fold(first, |acc, x| {lcm(acc, x)}).to_string()
|
|
|
|
}
|
|
|
|
pub mod prelude {
|
|
pub use super::part1;
|
|
pub use super::part2;
|
|
}
|
|
|