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::>(); 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::>(); let start_nodes = map.keys().into_iter().filter(|x| x.chars().last().unwrap() == 'A').collect::>(); 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; }