y2024d16p2
This commit is contained in:
		| @@ -1,7 +1,4 @@ | ||||
| use std::{ | ||||
|     collections::{HashMap, HashSet}, | ||||
|     error::Error, | ||||
| }; | ||||
| use std::{collections::HashMap, error::Error}; | ||||
|  | ||||
| use itertools::Itertools; | ||||
|  | ||||
| @@ -37,6 +34,7 @@ pub fn process_part1(input: &str) -> usize { | ||||
|     }]; | ||||
|     let mut arrived: Vec<Reindeer> = Vec::new(); | ||||
|     let mut visited = HashMap::new(); | ||||
|     let mut iter = 0; | ||||
|     while !next_paths.is_empty() { | ||||
|         next_paths = next_paths | ||||
|             .iter() | ||||
| @@ -59,7 +57,9 @@ pub fn process_part1(input: &str) -> usize { | ||||
|                 arrived.push(arrived_reindeer); | ||||
|             } | ||||
|         } | ||||
|         iter += 1; | ||||
|     } | ||||
|     println!("Iterations to goal {iter}"); | ||||
|     arrived.iter().map(|reindeer| reindeer.score).min().unwrap() | ||||
| } | ||||
|  | ||||
| @@ -89,15 +89,15 @@ pub fn process_part2(input: &str) -> usize { | ||||
|                 .collect_vec() | ||||
|         }) | ||||
|         .collect_vec(); | ||||
|     let mut visited = HashSet::new(); | ||||
|     visited.insert(start); | ||||
|     let mut smallest_score = usize::MAX; | ||||
|     let mut visited = HashMap::new(); | ||||
|     visited.insert((start, Orientation::East), 0); | ||||
|     let mut next_paths = vec![Reindeer { | ||||
|         coords: start, | ||||
|         visited, | ||||
|         visited: visited.clone(), | ||||
|         ..Default::default() | ||||
|     }]; | ||||
|     let mut arrived: Vec<Reindeer> = Vec::new(); | ||||
|     let mut visited = HashMap::new(); | ||||
|     while !next_paths.is_empty() { | ||||
|         next_paths = next_paths | ||||
|             .iter() | ||||
| @@ -105,33 +105,47 @@ pub fn process_part2(input: &str) -> usize { | ||||
|             .collect_vec() | ||||
|             .concat(); | ||||
|         for (idx, reindeer) in next_paths.clone().iter().enumerate().rev() { | ||||
|             if let Some(_score) = visited.get_mut(&reindeer.coords) { | ||||
|                 //if *score < reindeer.score { | ||||
|                 //    next_paths.remove(idx); | ||||
|                 //    continue; | ||||
|                 //} else { | ||||
|                 //    *score = reindeer.score; | ||||
|                 //} | ||||
|             } else { | ||||
|                 visited.insert(reindeer.coords, reindeer.score); | ||||
|             if reindeer.score > smallest_score | ||||
|                 || reindeer | ||||
|                     .visited | ||||
|                     .contains_key(&(reindeer.coords, reindeer.orientation)) | ||||
|             { | ||||
|                 next_paths.remove(idx); | ||||
|                 continue; | ||||
|             } | ||||
|             if reindeer.state == ReindeerState::Arrived { | ||||
|             next_paths[idx] | ||||
|                 .visited | ||||
|                 .insert((reindeer.coords, reindeer.orientation), reindeer.score); | ||||
|             if let Some(score) = visited.get_mut(&(reindeer.coords, reindeer.orientation)) { | ||||
|                 if *score < reindeer.score { | ||||
|                     next_paths.remove(idx); | ||||
|                     continue; | ||||
|                 } else { | ||||
|                     *score = reindeer.score; | ||||
|                 } | ||||
|             } else { | ||||
|                 visited.insert((reindeer.coords, reindeer.orientation), reindeer.score); | ||||
|             } | ||||
|             if reindeer.state == ReindeerState::Arrived && reindeer.score <= smallest_score { | ||||
|                 smallest_score = reindeer.score; | ||||
|                 let arrived_reindeer = next_paths.remove(idx); | ||||
|                 arrived.push(arrived_reindeer); | ||||
|             } | ||||
|         } | ||||
|         arrived.retain(|reindeer| reindeer.score == smallest_score); | ||||
|     } | ||||
|     let min_score = arrived.iter().map(|reindeer| reindeer.score).min().unwrap(); | ||||
|     let visited = arrived | ||||
|         .into_iter() | ||||
|         .filter(|reindeer| reindeer.score == min_score) | ||||
|         .collect_vec(); | ||||
|     println!("{visited:?}"); | ||||
|     let visited = visited | ||||
|         .into_iter() | ||||
|         .map(|reindeer| reindeer.visited.into_iter().collect_vec()) | ||||
|         .iter() | ||||
|         .map(|reindeer| { | ||||
|             reindeer | ||||
|                 .visited | ||||
|                 .keys() | ||||
|                 .map(|(coords, _)| coords) | ||||
|                 .collect_vec() | ||||
|         }) | ||||
|         .collect_vec() | ||||
|         .concat(); | ||||
|     log_maze(&grid, &arrived); | ||||
|     visited.iter().unique().count() | ||||
| } | ||||
|  | ||||
| @@ -177,7 +191,7 @@ struct Reindeer { | ||||
|     orientation: Orientation, | ||||
|     coords: (usize, usize), | ||||
|     score: usize, | ||||
|     visited: HashSet<(usize, usize)>, | ||||
|     visited: HashMap<((usize, usize), Orientation), usize>, | ||||
|     state: ReindeerState, | ||||
| } | ||||
|  | ||||
| @@ -195,28 +209,23 @@ impl Reindeer { | ||||
|             Orientation::South => (self.coords.0, self.coords.1 + 1), | ||||
|             Orientation::North => (self.coords.0, self.coords.1 - 1), | ||||
|         }; | ||||
|         let mut visited = self.visited.clone(); | ||||
|         visited.insert(coords); | ||||
|         if tile == GridTile::Wall { | ||||
|             Reindeer { | ||||
|                 state: ReindeerState::Stuck, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } else if tile == GridTile::End { | ||||
|             Reindeer { | ||||
|                 score: self.score + 1, | ||||
|                 state: ReindeerState::Arrived, | ||||
|                 coords, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } else { | ||||
|             Reindeer { | ||||
|                 score: self.score + 1, | ||||
|                 coords, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -234,13 +243,10 @@ impl Reindeer { | ||||
|             Orientation::South => (self.coords.0 - 1, self.coords.1), | ||||
|             Orientation::North => (self.coords.0 + 1, self.coords.1), | ||||
|         }; | ||||
|         let mut visited = self.visited.clone(); | ||||
|         visited.insert(coords); | ||||
|         if tile == GridTile::Wall { | ||||
|             Reindeer { | ||||
|                 state: ReindeerState::Stuck, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } else if tile == GridTile::End { | ||||
|             Reindeer { | ||||
| @@ -248,15 +254,14 @@ impl Reindeer { | ||||
|                 state: ReindeerState::Arrived, | ||||
|                 coords, | ||||
|                 orientation: self.orientation.turn_clockwise(), | ||||
|                 visited, | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } else { | ||||
|             Reindeer { | ||||
|                 score: self.score + 1001, | ||||
|                 orientation: self.orientation.turn_clockwise(), | ||||
|                 coords, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -274,13 +279,10 @@ impl Reindeer { | ||||
|             Orientation::South => (self.coords.0 + 1, self.coords.1), | ||||
|             Orientation::North => (self.coords.0 - 1, self.coords.1), | ||||
|         }; | ||||
|         let mut visited = self.visited.clone(); | ||||
|         visited.insert(coords); | ||||
|         if tile == GridTile::Wall { | ||||
|             Reindeer { | ||||
|                 state: ReindeerState::Stuck, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } else if tile == GridTile::End { | ||||
|             Reindeer { | ||||
| @@ -288,15 +290,14 @@ impl Reindeer { | ||||
|                 state: ReindeerState::Arrived, | ||||
|                 coords, | ||||
|                 orientation: self.orientation.turn_counterclockwise(), | ||||
|                 visited, | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } else { | ||||
|             Reindeer { | ||||
|                 score: self.score + 1001, | ||||
|                 orientation: self.orientation.turn_counterclockwise(), | ||||
|                 coords, | ||||
|                 visited, | ||||
|                 ..*self | ||||
|                 ..self.clone() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -342,6 +343,47 @@ impl TryFrom<char> for GridTile { | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn log_maze(grid: &[Vec<GridTile>], visited: &Vec<Reindeer>) { | ||||
|     for (yidx, row) in grid.iter().enumerate() { | ||||
|         for (xidx, tile) in row.iter().enumerate() { | ||||
|             let contains = { | ||||
|                 let mut contains = false; | ||||
|                 for reindeer in visited { | ||||
|                     if reindeer | ||||
|                         .visited | ||||
|                         .contains_key(&((xidx, yidx), Orientation::East)) | ||||
|                         || reindeer | ||||
|                             .visited | ||||
|                             .contains_key(&((xidx, yidx), Orientation::West)) | ||||
|                         || reindeer | ||||
|                             .visited | ||||
|                             .contains_key(&((xidx, yidx), Orientation::North)) | ||||
|                         || reindeer | ||||
|                             .visited | ||||
|                             .contains_key(&((xidx, yidx), Orientation::South)) | ||||
|                     { | ||||
|                         contains = true; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|                 contains | ||||
|             }; | ||||
|             if contains && !(*tile == GridTile::Start || *tile == GridTile::End) { | ||||
|                 print!("O"); | ||||
|             } else if *tile == GridTile::Wall { | ||||
|                 print!("#"); | ||||
|             } else if *tile == GridTile::Path { | ||||
|                 print!("."); | ||||
|             } else if *tile == GridTile::Start { | ||||
|                 print!("S"); | ||||
|             } else if *tile == GridTile::End { | ||||
|                 print!("E"); | ||||
|             } | ||||
|         } | ||||
|         println!(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user