73 lines
2.3 KiB
Rust
73 lines
2.3 KiB
Rust
use nom::{
|
|
bytes::complete::{take_until, take, tag},
|
|
character::complete::{
|
|
newline, multispace1, alphanumeric1,
|
|
},
|
|
sequence::{preceded, separated_pair},
|
|
multi::separated_list1,
|
|
IResult,
|
|
};
|
|
use std::collections::HashMap;
|
|
use std::str::Chars;
|
|
|
|
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;
|
|
let mut positions = start_nodes;
|
|
for _ in 0..10000000 {
|
|
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()
|
|
}
|
|
|
|
pub mod prelude {
|
|
pub use super::part1;
|
|
pub use super::part2;
|
|
}
|
|
|