use std::collections::{HashMap, VecDeque}; use base::read_file; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] struct Pos(usize, usize); impl Pos { fn left(&self) -> Self { Pos(self.0 - 1, self.1) } fn right(&self) -> Self { Pos(self.0 + 1, self.1) } fn up(&self) -> Self { Pos(self.0, self.1 - 1) } fn down(&self) -> Self { Pos(self.0, self.1 + 1) } fn getHeight(&self, tiles: &Vec>) -> u8 { return tiles[self.1][self.0]; } } fn get_positions(tiles: &Vec>, pos: Pos, width: usize, height: usize) -> Vec { let current_height = pos.getHeight(&tiles); let mut positions = vec![]; if pos.0 > 0 { positions.push(pos.left()) } if pos.1 > 0 { positions.push(pos.up()); } if pos.0 < width - 1 { positions.push(pos.right()); } if pos.1 < height - 1 { positions.push(pos.down()); } let mut i = 0; while i < positions.len() { if positions[i].getHeight(&tiles) > current_height + 1 { let _ = positions.remove(i); } else { i += 1; } } positions } fn pathfinding_dijkstra(start: Pos, end: Pos, tiles: &Vec>) -> Option { let height = tiles.len(); let width = tiles[0].len(); let mut discovered = HashMap::>::new(); discovered.insert(start, None); let mut to_search = VecDeque::new(); to_search.push_front(start); while !to_search.is_empty() { if let Some(u) = to_search.pop_back() { for position in get_positions(tiles, u, width, height) { if let None = discovered.get(&position) { discovered.insert(position, Some(u)); to_search.push_front(position); } } } } let mut position = end; let mut counter = 0; loop { if let Some(pre) = discovered.get(&position) { if let Some(pos) = pre { position = *pos; counter += 1; } else { break; } } else { return None; } } Some(counter) } fn main() { let lines = read_file("day12.txt"); let mut start = None; let mut end = None; let mut tiles = vec![]; let mut zero_height_tiles = vec![]; for (y, line) in lines.iter().enumerate() { tiles.push(vec![]); for (x, c) in line.bytes().enumerate() { match c { 83 => { let pos = Pos(x, y); start = Some(pos); zero_height_tiles.push(pos); tiles[y].push(0); } 69 => { end = Some(Pos(x, y)); tiles[y].push(25); } _ => { let height = c - 'a' as u8; tiles[y].push(height); if height == 0 { zero_height_tiles.push(Pos(x, y)); } } } } } println!("Task 1: {}", pathfinding_dijkstra(start.unwrap(), end.unwrap(), &tiles).unwrap()); let task2 = zero_height_tiles.iter().filter_map(|start| pathfinding_dijkstra(*start, end.unwrap(), &tiles)).min().unwrap(); println!("Task 2: {}", task2); }