use std::collections::HashMap; use std::collections::HashSet; use std::error::Error; use std::fs::File; use std::io::{self, BufRead}; use std::vec::Vec; fn get_risk(x: i32, y: i32, map: &Vec>) -> Option { let tw = map[0].len() as i32; let th = map.len() as i32; let mw = tw * 5; let mh = th * 5; if y >= 0 && y < mh as i32 && x >= 0 && x < mw as i32 { let tile_x = x / tw; let tile_y = y / th; let mx = x % tw; let my = y % th; let mut risk = map[my as usize][mx as usize] + tile_x as u32 + tile_y as u32; while risk > 9 { risk -= 9; } Some(risk) } else { None } } fn do_the_dijkstra( start_x: i32, start_y: i32, target_x: i32, target_y: i32, map: &Vec>, ) -> u32 { let mut unexplored: HashSet<(i32, i32)> = HashSet::new(); let mut path_risk: HashMap<(i32, i32), u32> = HashMap::new(); path_risk.insert((start_x, start_y), 0); //let mut predecessors: HashMap<(i32, i32), (i32, i32)> = HashMap::new(); for x in 0..target_x + 1 { for y in 0..target_y + 1 { unexplored.insert((x as i32, y as i32)); } } while !unexplored.is_empty() { let mut cur_node: Option<(i32, i32)> = None; let known_nodes: HashSet<(i32, i32)> = path_risk.keys().cloned().collect(); let candidates: HashSet<(i32, i32)> = unexplored.intersection(&known_nodes).cloned().collect(); for candidate in candidates.iter() { if let Some(node) = cur_node { if path_risk[candidate] < path_risk[&node] { cur_node = Some(*candidate); } } else { cur_node = Some(*candidate); } } let cur_node = cur_node.unwrap(); println!("{:?} {}", cur_node, unexplored.len()); unexplored.remove(&cur_node); if cur_node.0 == target_x && cur_node.1 == target_y { println!("Found my target!"); break; } for (dx, dy) in [(1, 0), (0, 1), (-1, 0), (0, -1)] { let neighboor = (cur_node.0 + dx, cur_node.1 + dy); if let Some(enter_risk) = get_risk(neighboor.1, neighboor.0, &map) { let alt_risk = path_risk[&cur_node] + enter_risk; if !path_risk.contains_key(&neighboor) { path_risk.insert(neighboor, alt_risk); } else if alt_risk < path_risk[&neighboor] { path_risk.insert(neighboor, alt_risk); } } } } path_risk[&(target_x, target_y)] } fn main() -> Result<(), Box> { let file = File::open("inputs/day15.txt")?; let map: Vec> = io::BufReader::new(file) .lines() .map(|l| { l.unwrap() .chars() .map(|c| c.to_string().parse().unwrap()) .collect() }) .collect(); let target_x = map[0].len() as i32 - 1; let target_y = map.len() as i32 - 1; let answer1 = do_the_dijkstra(0, 0, target_x, target_y, &map); let target2_x = (map[0].len() * 5) as i32 - 1; let target2_y = (map.len() * 5) as i32 - 1; let answer2 = do_the_dijkstra(0, 0, target2_x, target2_y, &map); println!("Answer1: {}", answer1); println!("Answer2: {}", answer2); Ok(()) }