diff options
Diffstat (limited to '2018/src')
| -rw-r--r-- | 2018/src/day13.rs | 176 | ||||
| -rw-r--r-- | 2018/src/main.rs | 4 | 
2 files changed, 179 insertions, 1 deletions
| diff --git a/2018/src/day13.rs b/2018/src/day13.rs new file mode 100644 index 0000000..13ff3a4 --- /dev/null +++ b/2018/src/day13.rs @@ -0,0 +1,176 @@ +use std::io; +use std::io::BufRead; +use std::collections::HashMap; + +#[derive(Clone, PartialEq, Eq, Hash)] +struct Pos { x: usize, y: usize } + +#[derive(Clone)] +struct Dir { x: i32, y: i32 } + +impl Dir { +    fn rotright(&self) -> Dir { +        Dir { x: -self.y, y: self.x } +    } + +    fn rotleft(&self) -> Dir { +        Dir { x: self.y, y: -self.x } +    } +} + +enum Choice { +    Left, +    Forward, +    Right, +} + +impl Choice { +    fn incr(&mut self) { +        match self { +            Choice::Left => *self = Choice::Forward, +            Choice::Forward => *self = Choice::Right, +            Choice::Right => *self = Choice::Left, +        } +    } + +    fn apply(&self, dir: &Dir) -> Dir { +        match self { +            Choice::Left => dir.rotleft(), +            Choice::Forward => dir.clone(), +            Choice::Right => dir.rotright(), +        } +    } +} + +struct Cart { +    pos: Pos, +    dir: Dir, +    choice: Choice, +} + +impl Cart { +    fn nextpos(&self) -> Pos { +        Pos { x: (self.pos.x as i32 + self.dir.x) as usize, +              y: (self.pos.y as i32 + self.dir.y) as usize } +    } +} + +fn newdir(dir: &Dir, c: u8) -> Dir { +    // println!(" newdir {},{} {}", dir.x, dir.y, std::char::from_u32(c as u32).unwrap()); +    if c == '|' as u8 || c == '-' as u8 { +        Dir { x: dir.x, y: dir.y } +    } else if c == '/' as u8 { +        if dir.y == 0 { +            dir.rotleft() +        } else { +            dir.rotright() +        } +    } else if c == '\\' as u8 { +        if dir.y == 0 { +            dir.rotright() +        } else { +            dir.rotleft() +        } +    } else { +        println!("<{}>", c); +        unreachable!(); +    } +} + +fn print_dir(dir: &Dir) -> char { +    match dir { +        Dir{x:1,y:0} => '>', +        Dir{x:-1,y:0} => '<', +        Dir{x:0,y:1} => 'v', +        Dir{x:0,y:-1} => '^', +        Dir{..} => '?', +    } +} + +fn print_grid(grid: &Vec<Vec<u8>>, carts: &Vec<Cart>) { +    let mut hascart: HashMap<Pos, usize> = HashMap::new(); +    for (i, cart) in carts.iter().enumerate() { +        hascart.insert(cart.pos.clone(), i); +    } + +    for y in 0..grid.len() { +        for x in 0..grid[y].len() { +            match hascart.get(&Pos { x, y }) { +                Some(&idx) => { +                    print!("{}", print_dir(&carts[idx].dir)); +                } +                None => { +                    print!("{}", std::char::from_u32(grid[y][x] as u32).unwrap()); +                } +            } +        } + +        println!(""); +    } +} + +pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> { +    let mut grid: Vec<Vec<u8>> = reader.lines().map(|l| l.unwrap().as_bytes().to_vec()).collect(); +    let h = grid.len(); +    let w = grid[0].len(); + +    let mut hascart = Vec::new(); +    for _ in 0..h { +        hascart.push(vec![false; w]); +    } + +    let mut carts: Vec<Cart> = Vec::new(); +    for y in 0..h { +        for x in 0..w { +            macro_rules! grid_process { +                ( $c1:expr, $c2:expr, $dx:expr, $dy:expr ) => { +                    if grid[y][x] == $c1 as u8 { +                        grid[y][x] = $c2 as u8; +                        carts.push(Cart { pos: Pos { x, y }, dir: Dir { x: $dx, y: $dy }, choice: Choice::Left }); +                        hascart[y][x] = true; +                    } +                } +            } + +            grid_process!('>', '-', 1, 0); +            grid_process!('<', '-', -1, 0); +            grid_process!('^', '|', 0, -1); +            grid_process!('v', '|', 0, 1); +        } +    } + +    let part1; + +    'outer: loop { +        for mut cart in &mut carts { +            let pos2 = cart.nextpos(); +            let c = grid[pos2.y][pos2.x]; + +            // println!("cart at {},{} {},{}", cart.pos.x, cart.pos.y, cart.dir.x, cart.dir.y); + +            let dir2; +            if c == '+' as u8 { +                dir2 = cart.choice.apply(&cart.dir); +                cart.choice.incr(); +            } else { +                dir2 = newdir(&cart.dir, c); +            } + +            if hascart[pos2.y][pos2.x] { +                part1 = format!("{},{}", pos2.x, pos2.y); +                break 'outer; +            } + +            hascart[cart.pos.y][cart.pos.x] = false; +            hascart[pos2.y][pos2.x] = true; +            cart.pos = pos2; +            cart.dir = dir2; +        } + +        carts.sort_by_key(|cart| (cart.pos.y, cart.pos.x)); + +        // print_grid(&grid, &carts); +    } + +    Ok((part1, String::new())) +} diff --git a/2018/src/main.rs b/2018/src/main.rs index daafaa4..27125d3 100644 --- a/2018/src/main.rs +++ b/2018/src/main.rs @@ -17,8 +17,9 @@ mod day9;  mod day10;  mod day11;  mod day12; +mod day13; -static NUM_DAYS: i32 = 12; +static NUM_DAYS: i32 = 13;  fn day_switch<T: BufRead>(day: i32, reader: T) -> io::Result<(String, String)> {      match day { @@ -34,6 +35,7 @@ fn day_switch<T: BufRead>(day: i32, reader: T) -> io::Result<(String, String)> {          10 => day10::main(reader),          11 => day11::main(reader),          12 => day12::main(reader), +        13 => day13::main(reader),          _ => Err(Error::new(ErrorKind::Other, "Invalid day"))      }  } | 
