aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

a.rs (2225B)


      1 use std::cmp::max;
      2 mod common;
      3 use common::*;
      4 
      5 #[derive(Copy, Clone, Debug)]
      6 pub struct Position {
      7     pub i: usize,
      8     pub j: usize,
      9     pub d: Direction
     10 }
     11 
     12 pub struct Map {
     13     pub tiles: Vec<Vec<Tile>>
     14 }
     15 
     16 type StepFn = fn(&Map, Position) -> Position;
     17 
     18 impl Map {
     19     pub fn from_stdin() -> Map {
     20         let mut maxlen = 0;
     21         let mut tiles = vec![];
     22         let mut line = String::new();
     23         while std::io::stdin().read_line(&mut line).unwrap() > 1 {
     24             let v = line[0..line.len()-1].as_bytes().iter()
     25                 .map(|b| Tile::from_byte(*b)).collect::<Vec<_>>();
     26             maxlen = max(maxlen, v.len());
     27             tiles.push(v);
     28             line.clear();
     29         }
     30         for v in &mut tiles {
     31             while v.len() < maxlen { v.push(Tile::Skip); }
     32         }
     33         Map { tiles }
     34     }
     35 
     36     pub fn start_position(&self) -> Position {
     37         let first_valid = self.tiles[0].iter()
     38             .position(|t| *t == Tile::Walk).unwrap();
     39         Position { i: 0, j: first_valid, d: Direction::Right }
     40     }
     41 
     42     pub fn walk(&self, pos: Position, n: usize, step: StepFn) -> Position {
     43         let mut p = pos;
     44         for _ in 0..n { p = step(self, p); }
     45         p
     46     }
     47 }
     48 
     49 fn step(map: &Map, position: Position) -> Position {
     50     let imax = map.tiles.len();
     51     let jmax = map.tiles[0].len();
     52     let s = position.d.step();
     53     let mut p = position;
     54     loop {
     55         let inext = ((s.0 + imax as i64) as usize + p.i) % imax;
     56         let jnext = ((s.1 + jmax as i64) as usize + p.j) % jmax;
     57         p = Position { i: inext, j: jnext, d: p.d };
     58         match map.tiles[p.i][p.j] {
     59             Tile::Walk => return p,
     60             Tile::Wall => return position,
     61             Tile::Skip => ()
     62         }
     63     }
     64 }
     65 
     66 fn password(p: Position) -> usize {
     67     1000 * (p.i+1) + 4 * (p.j+1) + p.d.value()
     68 }
     69 
     70 fn main() {
     71     let map = Map::from_stdin();
     72     let (turns, steps) = read_instruction_line_from_stdin();
     73     let mut position = map.start_position();
     74 
     75     for i in 0..turns.len() {
     76         position = map.walk(position, steps[i], step);
     77         position.d = position.d.turn(turns[i]);
     78     }
     79     position = map.walk(position, steps[steps.len()-1], step);
     80     println!("{}", password(position));
     81 }