use std::{fs, env, collections::HashMap}; fn read_input(path: &str) -> String { return fs::read_to_string(path).expect("Cannot read file."); } fn parse_input(s: &str) -> Vec> { return s.lines() .map(|l| l.chars().filter_map(|e| e.to_digit(10)).collect()) .collect(); } fn expand_map(m: &Vec>) -> Vec> { let mut t = vec![]; for l in 0..(5 * m.len()) { t.push(vec![]); for c in 0..(5 * m.len()) { let x = (m[l % m.len()][c % m[0].len()] + (l / m.len() + c / m[0].len()) as u32) % 9; t[l].push(if x == 0 { 9 } else { x }); } } return t; } fn get_shortest_risk(m: &Vec>, mut l: usize, mut c: usize) -> u32 { let mut w = HashMap::new(); w.insert((l, c), 0); let mut q = vec![(0, l, c)]; while !q.is_empty() { let e = q.pop().unwrap(); l = e.1; c = e.2; let z = *w.get(&(l, c)).unwrap(); let mut p = vec![]; if c > 0 { p.push((l, c - 1)); } if l > 0 { p.push((l - 1, c)); } if c < m[l].len() - 1 { p.push((l, c + 1)); } if l < m.len() - 1 { p.push((l + 1, c)); } while !p.is_empty() { let a = p.pop().unwrap(); let x = *w.get(&a).unwrap_or(&u32::MAX); if x > z + m[a.0][a.1] { w.insert(a, z + m[a.0][a.1]); q.push((z + m[a.0][a.1], a.0, a.1)); } } q.sort_by(|a, b| b.cmp(a)); } return *w.get(&(m.len() - 1, m[m.len() - 1].len() - 1)).unwrap_or(&u32::MAX); } fn main() { let args: Vec = env::args().collect(); for arg in args.iter().skip(1) { let input = read_input(&arg); let vec_in = parse_input(&input); let exp = expand_map(&vec_in); println!("[{}]", &arg); println!("\t[Part 1] => Answer is '{}'.", get_shortest_risk(&vec_in, 0, 0)); println!("\t[Part 2] => Answer is '{}'.", get_shortest_risk(&exp, 0, 0)); } }