diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2018-12-13 12:19:32 +0100 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2018-12-13 12:19:32 +0100 |
commit | f1237b2dbfdd5940ea6474581574be64d818d355 (patch) | |
tree | c28eca93ab41ac51224915233f342990d0ec1b5e /2018/src | |
parent | 7a15bcbeb8a86f3202ae55ca610384991806e443 (diff) |
Day 13 part 1
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")) } } |