Advertisement
Guest User

Rust Advent of Code 2019 Day 18

a guest
Dec 18th, 2019
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 7.15 KB | None | 0 0
  1. use std::collections::{HashMap, HashSet};
  2. use std::fs;
  3. use std::fmt::{Debug, Display, Error, Formatter};
  4. use std::ops::{Sub, Add, AddAssign};
  5.  
  6. use queue::Queue;
  7.  
  8.  
  9. #[derive(Hash)]
  10. pub struct Point {
  11.     pub x: isize,
  12.     pub y: isize
  13. }
  14.  
  15. impl Point {
  16.     pub fn new(x: isize, y: isize) -> Self {
  17.         Self { x, y }
  18.     }
  19. }
  20.  
  21. impl PartialEq for Point {
  22.     fn eq(&self, other: &Self) -> bool {
  23.         self.x.eq(&other.x) && self.y.eq(&other.y)
  24.     }
  25. }
  26.  
  27. impl Eq for Point {}
  28.  
  29. impl Sub for Point {
  30.     type Output = Self;
  31.  
  32.     fn sub(self, rhs: Self) -> Self::Output {
  33.         Self { x: self.x - rhs.x, y: self.y - rhs.y }
  34.     }
  35. }
  36.  
  37. impl Add for Point {
  38.     type Output = Self;
  39.  
  40.     fn add(self, rhs: Self) -> Self::Output {
  41.         Self { x: self.x + rhs.x, y: self.y + rhs.y }
  42.     }
  43. }
  44.  
  45. impl AddAssign for Point {
  46.     fn add_assign(&mut self, rhs: Self) {
  47.         self.x += rhs.x;
  48.         self.y += rhs.y;
  49.     }
  50. }
  51.  
  52. impl Copy for Point {
  53.  
  54. }
  55.  
  56. impl Clone for Point {
  57.     fn clone(&self) -> Self {
  58.         Self { x: self.x.clone(), y: self.y.clone() }
  59.     }
  60. }
  61.  
  62. impl Debug for Point {
  63.     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
  64.        write!(f, "({}, {})", self.x, self.y)
  65.    }
  66. }
  67.  
  68. impl Display for Point {
  69.    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
  70.         write!(f, "({}, {})", self.x, self.y)
  71.     }
  72. }
  73.  
  74. #[derive(Clone, Hash, Debug, Eq, PartialEq)]
  75. struct State {
  76.     at: Vec<char>,
  77.     obtained_keys: Vec<char>,
  78. }
  79.  
  80. struct Map {
  81.     path: HashSet<Point>,
  82.     doors: HashMap<Point, char>,
  83. }
  84.  
  85. fn main() {
  86.     let input = fs::read_to_string("input2").unwrap();
  87.     let (distances, num_keys) = load(&input);
  88.     let state = State {
  89.         at: vec![0 as char, 1 as char, 2 as char, 3 as char],
  90.         obtained_keys: Vec::new(),
  91.     };
  92. //    println!("{:?}: {:?}, {:?}, {:?}", distances, num_positions, num_keys, state);
  93.     let mut previous = HashMap::new();
  94.     println!("{:?}", minimum_steps(&state, &distances, num_keys, &mut previous));
  95. }
  96.  
  97. fn load(input: &String) -> (HashMap<(char, char), (usize, Vec<char>)>, usize) {
  98.     let path: HashSet<Point> = input.split('\n').enumerate()
  99.         .flat_map(|(y, line)| {
  100.             line.chars().enumerate()
  101.                 .filter(|(_, character)| *character != '#')
  102.                 .map(|(x, _)| {
  103.                     Point::new(x as isize, y as isize)
  104.                 })
  105.                 .collect::<HashSet<Point>>()
  106.         })
  107.         .collect();
  108.     let no_letter_characters = vec!['#', '.', '@'];
  109.     let keys: HashMap<Point, char> = input.split('\n').enumerate()
  110.         .flat_map(|(y, line)|
  111.             line.chars().enumerate()
  112.                 .filter(|(_, character)| !no_letter_characters.contains(character) && character.to_lowercase().next().unwrap() == *character)
  113.                 .map(|(x, character)| (Point::new(x as isize, y as isize), character.to_uppercase().next().unwrap()))
  114.                 .collect::<Vec<(Point, char)>>())
  115.         .collect();
  116.     let doors = input.split('\n').enumerate()
  117.         .flat_map(|(y, line)|
  118.             line.chars().enumerate()
  119.                 .filter(|(_, character)| !no_letter_characters.contains(character) && character.to_uppercase().next().unwrap() == *character)
  120.                 .map(|(x, character)| (Point::new(x as isize, y as isize), character))
  121.                 .collect::<Vec<(Point, char)>>())
  122.         .collect();
  123.     let positions: Vec<Point> = input.split('\n').enumerate()
  124.         .flat_map(|(y, line)|
  125.             line.chars().enumerate()
  126.                 .filter(|(_, character)| *character == '@')
  127.                 .map(|(x, _)| Point::new(x as isize, y as isize))
  128.                 .collect::<Vec<Point>>())
  129.         .collect();
  130.     let map = Map { path, doors };
  131.     let identified_positions: HashMap<Point, char> = positions
  132.         .iter()
  133.         .enumerate()
  134.         .map(|(i, point)| (point.clone(), i as u8 as char))
  135.         .collect();
  136.     (keys.clone().into_iter()
  137.          .chain(identified_positions)
  138.          .flat_map(|(point_one, key_one)|
  139.              keys.iter().filter_map(|(point_two, key_two)| {
  140.                  match bfs(&map, &point_one, point_two) {
  141.                      Some(result) => Some(((key_one.clone(), key_two.clone()), result)),
  142.                      None => None
  143.                  }
  144.              })
  145.                  .collect::<Vec<((char, char), (usize, Vec<char>))>>())
  146.          .collect(), keys.len())
  147. }
  148.  
  149. fn get_accessible_neighbors(current_position: &Point, map: &Map) -> Vec<Point> {
  150.     let neighbors = [current_position.clone() - Point::new(1, 0), current_position.clone() + Point::new(1, 0),
  151.         current_position.clone() - Point::new(0, 1), current_position.clone() + Point::new(0, 1)];
  152.     neighbors.iter()
  153.         .filter(|neighbor| map.path.contains(neighbor))
  154.         .map(|neighbor| neighbor.clone())
  155.         .collect()
  156. }
  157.  
  158. fn bfs(map: &Map, from: &Point, to: &Point) -> Option<(usize, Vec<char>)> {
  159.     let mut queue: Queue<(Point, usize, Vec<char>)> = Queue::new();
  160.     let mut visited: HashSet<Point> = HashSet::new();
  161.  
  162.     queue.queue((from.clone(), 0, Vec::new())).unwrap();
  163.     visited.insert(from.clone());
  164.     while !queue.is_empty() {
  165.         let (current_pos, steps, necessary) = queue.dequeue().unwrap();
  166.         if &current_pos == to {
  167.             return Some((steps, necessary));
  168.         }
  169.         let mut new_neccessary = necessary.clone();
  170.         if map.doors.contains_key(&current_pos) {
  171.             new_neccessary.push(map.doors.get(&current_pos).unwrap().clone());
  172.         }
  173.         for neighbor in get_accessible_neighbors(&current_pos, map) {
  174.             if !visited.contains(&neighbor) {
  175.                 queue.queue((neighbor, steps + 1, new_neccessary.clone())).unwrap();
  176.                 visited.insert(neighbor.clone());
  177.             }
  178.         }
  179.     }
  180.     None
  181. }
  182.  
  183. fn minimum_steps(state: &State, distances: &HashMap<(char, char), (usize, Vec<char>)>, num_keys: usize, previous_states: &mut HashMap<State, usize>) -> usize {
  184.     if num_keys == state.obtained_keys.len() {
  185.         return 0;
  186.     }
  187.     if previous_states.contains_key(state) {
  188.         return previous_states.get(state).unwrap().clone();
  189.     }
  190.  
  191.     let mut min_steps = std::usize::MAX;
  192.     let next_stops = distances.iter()
  193.         .filter(|((from, to), (_, required_keys))| !state.obtained_keys.contains(to) && state.at.contains(from) && required_keys.iter().find(|key| !state.obtained_keys.contains(key)).is_none())
  194.             .map(|((from, to), (steps, _))| (state.at.iter().position(|i| i == from).unwrap(), to, steps));
  195.     for (robot, next_stop, steps) in next_stops {
  196.         let mut new_obtained_keys: Vec<char> = state.obtained_keys.iter().chain(vec![next_stop]).cloned().collect();
  197.         new_obtained_keys.sort();
  198.         let new_state = State {
  199.             obtained_keys: new_obtained_keys,
  200.             at: state.at.clone().iter().enumerate().map(|(i, at)| if i == robot { next_stop.clone() } else { at.clone() }).collect(),
  201.         };
  202.         min_steps = min_steps.min(minimum_steps(&new_state, distances, num_keys, previous_states) + steps.clone());
  203.     }
  204.     previous_states.insert(state.clone(), min_steps);
  205.     min_steps
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement