64 lines
2.0 KiB
Rust
64 lines
2.0 KiB
Rust
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<Vec<u32>> {
|
|
return s.lines()
|
|
.map(|l| l.chars().filter_map(|e| e.to_digit(10)).collect())
|
|
.collect();
|
|
}
|
|
|
|
fn expand_map(m: &Vec<Vec<u32>>) -> Vec<Vec<u32>> {
|
|
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<Vec<u32>>, 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<String> = 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));
|
|
}
|
|
}
|
|
|