diff --git a/src/tasks/day20.rs b/src/tasks/day20.rs index bbb501a..467c4e1 100644 --- a/src/tasks/day20.rs +++ b/src/tasks/day20.rs @@ -1,9 +1,8 @@ use self::Tile::*; #[allow(unused_imports)] use crate::utils; -use std::collections::{HashMap, HashSet}; -use std::ops::Add; use std::collections::VecDeque; +use std::collections::{HashMap, HashSet}; pub fn task1() { let input = utils::read_file("input/day20.txt"); @@ -15,7 +14,14 @@ pub fn task1() { // print_map(&map); - println!("Most distant point: {:?}", longest_shortest_path(&map, Point(0,0))); + println!( + "Most distant point: {:?}", + longest_shortest_path(&map, Point(0, 0)) + ); + println!( + "Rooms with minimal distance >= 1000: {}", + count_long_distances(&map, Point(0, 0), 1000) + ); } /// Returns the end points of the parsed input @@ -23,7 +29,7 @@ fn parse_input(map: &mut HashMap, input: &str, position: Point) -> // println!("{}, {:?}", input, position); if input == "$" { println!("End of the road."); - return vec!(position).into_iter().collect(); + return vec![position].into_iter().collect(); } let mut position = position; let mut input = input; @@ -81,7 +87,7 @@ fn parse_input(map: &mut HashMap, input: &str, position: Point) -> ), } } - vec!(position).into_iter().collect() + vec![position].into_iter().collect() } /// Splits the input by '|', but only by those that are not enclosed by further parenthesises. @@ -167,9 +173,9 @@ fn print_map(map: &HashMap) { fn longest_shortest_path(map: &HashMap, start: Point) -> Option<(Point, usize)> { let mut distances: HashMap = HashMap::with_capacity(map.len()); - let mut open: VecDeque<(usize,Point)> = VecDeque::new(); + let mut open: VecDeque<(usize, Point)> = VecDeque::new(); let mut visited: HashSet = HashSet::new(); - open.push_back((0,start)); + open.push_back((0, start)); visited.insert(start); while let Some((distance, predecessor)) = open.pop_front() { distances.insert(predecessor, distance); @@ -178,7 +184,7 @@ fn longest_shortest_path(map: &HashMap, start: Point) -> Option<(Po let room = predecessor.next_room(&p); if !visited.contains(&room) { visited.insert(room); - open.push_back((distance + 1, room)); + open.push_back((distance + 1, room)); } } } @@ -190,6 +196,30 @@ fn longest_shortest_path(map: &HashMap, start: Point) -> Option<(Po } } +fn count_long_distances(map: &HashMap, start: Point, threshold: usize) -> usize { + let mut distances: HashMap = HashMap::with_capacity(map.len()); + let mut open: VecDeque<(usize, Point)> = VecDeque::new(); + let mut visited: HashSet = HashSet::new(); + open.push_back((0, start)); + visited.insert(start); + while let Some((distance, predecessor)) = open.pop_front() { + distances.insert(predecessor, distance); + for p in predecessor.neighbors() { + if let Some(Door) = map.get(&p) { + let room = predecessor.next_room(&p); + if !visited.contains(&room) { + visited.insert(room); + open.push_back((distance + 1, room)); + } + } + } + } + distances + .iter() + .filter(|(_, distance)| **distance >= threshold) + .count() +} + #[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)] struct Point(i32, i32); @@ -213,7 +243,10 @@ impl Point { } fn next_room(&self, other: &Self) -> Self { - Point(self.0 + 2*(other.0 - self.0), self.1 +2*(other.1-self.1)) + Point( + self.0 + 2 * (other.0 - self.0), + self.1 + 2 * (other.1 - self.1), + ) } }