diff --git a/2019/17/src/main.rs b/2019/17/src/main.rs index b84257f..94c088c 100644 --- a/2019/17/src/main.rs +++ b/2019/17/src/main.rs @@ -2,6 +2,70 @@ use grid::*; use intcode::*; use std::char; use std::collections::HashMap; +use std::fmt; + +#[derive(Debug, PartialEq)] +struct Movement { + rotation: i8, + distance: u8, +} + +impl fmt::Display for Movement { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let dir_char = if self.rotation == 1 { 'R' } else { 'L' }; + write!(f, "{}{}", dir_char, self.distance) + } +} + +#[rustfmt::skip] +fn find_commands(field: &HashMap) -> Vec { + let mut robot_position = field.iter().find(|(_, c)| *c == &'^').unwrap().0.to_owned(); + let mut robot_direction = Direction::Up; + let mut commands = Vec::new(); + loop { + let mut steps = 0; + let turn = if field.get(&(robot_position + (robot_direction + 1))) == Some(&'#') { + 1 + } else { + -1 + }; + robot_direction += turn; + while field.get(&(robot_position + robot_direction)) == Some(&'#') { + robot_position += robot_direction; + steps += 1; + } + commands.push(Movement { + distance: steps, + rotation: turn, + }); + if robot_position.neighbors().iter().filter(|(_, p)| field.get(p) == Some(&'#')).count() == 1 { + break; + } + } + commands +} + +fn test_input() -> HashMap { + "#######...##### +#.....#...#...# +#.....#...#...# +......#...#...# +......#...###.# +......#.....#.# +^########...#.# +......#.#...#.# +......######### +........#...#.. +....#########.. +....#...#...... +....#...#...... +....#...#...... +....#####......" + .lines() + .enumerate() + .flat_map(move |(y, s)| s.chars().enumerate().map(move |(x, c)| ((x, y).into(), c))) + .collect() +} fn main() { // The main reason I use a hashmap here (instead of a 2D vector) is that my abstractions for @@ -15,10 +79,22 @@ fn main() { .enumerate() .flat_map(move |(y, s)| s.chars().enumerate().map(move |(x, c)| ((x, y).into(), c))) .collect(); + // let field = test_input(); let p1 = field - .keys() - .filter(|pos| field.get(&pos) == Some(&'#') && pos.neighbors().iter().all(|(_, p)| field.get(&p) == Some(&'#'))) - .fold(0, |acc, pos| acc + pos.x * pos.y); + .iter() + .filter(|(pos, obj)| { + *obj == &'#' + && pos + .neighbors() + .iter() + .all(|(_, p)| field.get(&p) == Some(&'#')) + }) + .fold(0, |acc, (pos, _)| acc + pos.x * pos.y); println!("Part 1: {}", p1); - // println!("{}", draw_ascii(&field, '.')); + println!("{}", draw_ascii(&field, '.')); + + let commands = find_commands(&field); + for c in &commands { + print!("{}", c); + } } diff --git a/2019/grid/src/lib.rs b/2019/grid/src/lib.rs index 1d6164a..b48c72f 100644 --- a/2019/grid/src/lib.rs +++ b/2019/grid/src/lib.rs @@ -77,36 +77,42 @@ impl Position2D { impl Direction { pub fn turn(&mut self, turn_value: i64) { - *self = match turn_value { - -1 => match self { + *self = *self + turn_value as i8; + } +} + +impl_op!(+ |a: Direction, b: i8| -> Direction { + match b { + -1 => match a { Direction::Up => Direction::Left, Direction::Right => Direction::Up, Direction::Down => Direction::Right, Direction::Left => Direction::Down, }, - 1 => match self { + 1 => match a { Direction::Up => Direction::Right, Direction::Right => Direction::Down, Direction::Down => Direction::Left, Direction::Left => Direction::Up, }, - 0 => *self, + 0 => a, n => unreachable!(format!("Illegal turn value: {}", n)), } - } -} +}); impl_op!(+ |a: Position2D, b: Position2D| -> Position2D { Position2D { x: a.x + b.x, y: a.y + b.y } }); + impl_op!(-|a: Position2D, b: Position2D| -> Position2D { Position2D { x: a.x - b.x, y: a.y - b.y, } }); + impl_op!(+ |a: Position2D, b: Direction| -> Position2D { a + match b { Direction::Up => Position2D::from((0, 1)), Direction::Right => Position2D::from((1, 0)), @@ -115,6 +121,12 @@ impl_op!(+ |a: Position2D, b: Direction| -> Position2D { a + match b { } }); +impl AddAssign for Direction { + fn add_assign(&mut self, rhs: i8) { + *self = *self + rhs; + } +} + impl AddAssign for Position2D { fn add_assign(&mut self, rhs: Direction) { *self = *self + rhs;