advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.rs (5042B)

    1 use std::collections::{HashMap, HashSet};
    2 
    3 #[derive(Debug, Clone, Copy)]
    4 enum Tile {
    5     Empty,
    6     Wall,
    7 }
    8 
    9 #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
   10 enum Dir {
   11     North,
   12     East,
   13     South,
   14     West,
   15 }
   16 
   17 impl Dir {
   18     fn left(&self) -> Self {
   19         match self {
   20             Self::North => Self::West,
   21             Self::West => Self::South,
   22             Self::South => Self::East,
   23             Self::East => Self::North,
   24         }
   25     }
   26 
   27     fn right(&self) -> Self {
   28         match self {
   29             Self::North => Self::East,
   30             Self::East => Self::South,
   31             Self::South => Self::West,
   32             Self::West => Self::North,
   33         }
   34     }
   35 
   36     fn opposite(&self) -> Self {
   37         self.right().right()
   38     }
   39 
   40     fn go(&self, (x, y): &(i32, i32)) -> (i32, i32) {
   41         let (dx, dy) = match self {
   42             Self::North => (-1, 0),
   43             Self::East => (0, 1),
   44             Self::South => (1, 0),
   45             Self::West => (0, -1),
   46         };
   47         (x + dx, y + dy)
   48     }
   49 
   50     fn val(&self) -> i32 {
   51         match self {
   52             Self::North => 3,
   53             Self::East => 0,
   54             Self::South => 1,
   55             Self::West => 2,
   56         }
   57     }
   58 }
   59 
   60 #[derive(Debug, Clone, Copy)]
   61 enum Step {
   62     Move(i32),
   63     TurnR,
   64     TurnL,
   65 }
   66 
   67 impl Step {
   68     fn parse_path(s: &str) -> Vec<Step> {
   69         let mut path = Vec::new();
   70         let mut buf = String::new();
   71         for c in s.trim().chars() {
   72             match c {
   73                 'L' => {
   74                     if buf.len() > 0 {
   75                         path.push(Self::Move(buf.parse::<i32>().unwrap()));
   76                         buf.clear();
   77                     }
   78                     path.push(Self::TurnL);
   79                 }
   80                 'R' => {
   81                     if buf.len() > 0 {
   82                         path.push(Self::Move(buf.parse::<i32>().unwrap()));
   83                         buf.clear();
   84                     }
   85                     path.push(Self::TurnR);
   86                 }
   87                 c => {
   88                     buf.push(c);
   89                 }
   90             }
   91         }
   92         if buf.len() > 0 {
   93             path.push(Self::Move(buf.parse::<i32>().unwrap()));
   94             buf.clear();
   95         }
   96         path
   97     }
   98 }
   99 
  100 fn main() {
  101     let (map, path) = {
  102         let tmp = std::fs::read_to_string("input.txt")
  103             .unwrap()
  104             .split("\n\n")
  105             .map(|s| s.to_string())
  106             .collect::<Vec<String>>();
  107         let map_lines = tmp[0]
  108             .split("\n")
  109             .map(|s| s.to_string())
  110             .collect::<Vec<String>>();
  111         let mut map = HashMap::new();
  112         for (i, s) in map_lines.iter().enumerate() {
  113             for (j, c) in s.chars().enumerate() {
  114                 match c {
  115                     '#' => {
  116                         map.insert((i as i32 + 1, j as i32 + 1), Tile::Wall);
  117                     }
  118                     '.' => {
  119                         map.insert((i as i32 + 1, j as i32 + 1), Tile::Empty);
  120                     }
  121                     _ => (),
  122                 }
  123             }
  124         }
  125         (map, Step::parse_path(&tmp[1]))
  126     };
  127     // 55244
  128     println!("Part 1: {}", part_1(&map, &path));
  129     //
  130     // println!("Part 2: {}", part_2(&map, &path));
  131 }
  132 
  133 fn warp(map: &HashMap<(i32, i32), Tile>, pos: &(i32, i32), dir: Dir) -> (i32, i32) {
  134     let mut prev = *pos;
  135     let mut next = *pos;
  136     let back_dir = dir.opposite();
  137     while map.contains_key(&next) {
  138         prev = next;
  139         next = back_dir.go(&prev);
  140     }
  141     prev
  142 }
  143 
  144 fn part_1(map: &HashMap<(i32, i32), Tile>, path: &Vec<Step>) -> i32 {
  145     let start_x = *map.keys().map(|(x, _)| x).min().unwrap();
  146     let start_y = *map
  147         .keys()
  148         .filter_map(|(x, y)| if *x == start_x { Some(y) } else { None })
  149         .min()
  150         .unwrap();
  151     let mut warp_dict = HashMap::new();
  152     let mut pos = (start_x, start_y);
  153     let mut dir = Dir::East;
  154     for step in path {
  155         match step {
  156             Step::Move(dist) => {
  157                 for _ in 0..*dist {
  158                     let mut next = dir.go(&pos);
  159                     if !map.contains_key(&next) {
  160                         if let Some(w) = warp_dict.get(&(pos, dir)) {
  161                             next = *w;
  162                         } else {
  163                             next = warp(map, &pos, dir);
  164                             warp_dict.insert((pos, dir), next);
  165                             warp_dict.insert((next, dir.opposite()), pos);
  166                         }
  167                     }
  168                     match map.get(&next).unwrap() {
  169                         Tile::Empty => {
  170                             pos = next;
  171                         }
  172                         Tile::Wall => {
  173                             break;
  174                         }
  175                     }
  176                 }
  177             }
  178             Step::TurnL => {
  179                 dir = dir.left();
  180             }
  181             Step::TurnR => {
  182                 dir = dir.right();
  183             }
  184         }
  185     }
  186     pos.0 * 1000 + pos.1 * 4 + dir.val()
  187 }