use core::panic; use std::collections::{HashMap, HashSet}; use utils::{math::factorial, permutation::nth_lex}; pub fn process_part1(input: &str) -> u32 { let mut distances = HashMap::new(); let mut locations = HashSet::new(); input.lines().for_each(|line| { let (direction, distance) = line.split_once(" = ").unwrap(); let (from, to) = direction.split_once(" to ").unwrap(); let distance = distance.parse::().unwrap(); distances.insert((from.to_string(), to.to_string()), distance); locations.insert(from.to_string()); locations.insert(to.to_string()); }); let locations = locations .iter() .map(|place| place.to_string()) .collect::>(); let num_permutations = factorial(locations.len().try_into().unwrap()); let mut shortest = u32::MAX; for idx in 1..=num_permutations { let perm = nth_lex(locations.clone(), idx.try_into().unwrap()).unwrap(); let route_length = get_route_length(perm, &distances); if route_length < shortest { shortest = route_length; } } shortest } fn get_route_length(route: Vec, distances: &HashMap<(String, String), u32>) -> u32 { route .windows(2) .map(|pair| { let distance = distances.get(&(pair[0].clone(), pair[1].clone())); if let Some(distance) = distance { return distance; } let distance = distances.get(&(pair[1].clone(), pair[0].clone())); if let Some(distance) = distance { return distance; } panic!("Should not happen"); }) .sum() } pub fn process_part2(input: &str) -> u32 { let mut distances = HashMap::new(); let mut locations = HashSet::new(); input.lines().for_each(|line| { let (direction, distance) = line.split_once(" = ").unwrap(); let (from, to) = direction.split_once(" to ").unwrap(); let distance = distance.parse::().unwrap(); distances.insert((from.to_string(), to.to_string()), distance); locations.insert(from.to_string()); locations.insert(to.to_string()); }); let locations = locations .iter() .map(|place| place.to_string()) .collect::>(); let num_permutations = factorial(locations.len().try_into().unwrap()); let mut longest = 0; for idx in 1..=num_permutations { let perm = nth_lex(locations.clone(), idx.try_into().unwrap()).unwrap(); let route_length = get_route_length(perm, &distances); if route_length > longest { longest = route_length; } } longest } #[cfg(test)] mod tests { use super::*; const INPUT: &str = "London to Dublin = 464 London to Belfast = 518 Dublin to Belfast = 141"; #[test] fn part1() { let result = process_part1(INPUT); assert_eq!(result, 605); } #[test] fn part2() { let result = process_part2(INPUT); assert_eq!(result, 982); } }