Robot Simulator
1. Readme
机器人模拟器
编写机器人模拟器。
机器人工厂的测试设施需要一个程序,来验证机器人的运动。
机器人有三种可能的运动:
- 右转
- 左转
- 前进
机器人被放置在一个假设的无限网格上,以一组{x,y}坐标,例如{3,8}面向特定方向(北、东、南或西),能向北和东前进。
然后,机器人接收许多指令,测试设备验证机器人的新位置以及指向哪个方向。
- 字母串”RAALAR”的意思是:
- 右转
- 前两次
- 向左拐
- 前一次
- 再次左转
- 假设一个机器人从{ 7, 3 }向北开始,然后运行这个指令流,它应该就放在面向西方的{ 9, 4 }上。
源
灵感来自一个著名公司的面试问题.
2. 开始你的表演
// The code below is a stub. Just enough to satisfy the compiler. // In order to pass the tests you can add-to or change any of this code. #[derive(PartialEq, Debug)] pub enum Direction { North, East, South, West, } pub struct Robot; impl Robot { pub fn new(x: i32, y: i32, d: Direction) -> Self { unimplemented!("Create a robot at (x, y) ({}, {}) facing {:?}", x, y, d,) } pub fn turn_right(self) -> Self { unimplemented!() } pub fn turn_left(self) -> Self { unimplemented!() } pub fn advance(self) -> Self { unimplemented!() } pub fn instructions(self, instructions: &str) -> Self { unimplemented!( "Follow the given sequence of instructions: {}", instructions ) } pub fn position(&self) -> (i32, i32) { unimplemented!() } pub fn direction(&self) -> &Direction { unimplemented!() } }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { #[test] fn robots_are_created_with_position_and_direction() { let robot = Robot::new(0, 0, Direction::North); assert_eq!((0, 0), robot.position()); assert_eq!(&Direction::North, robot.direction()); } #[test] //#[ignore] fn positions_can_be_negative() { let robot = Robot::new(-1, -1, Direction::South); assert_eq!((-1, -1), robot.position()); assert_eq!(&Direction::South, robot.direction()); } #[test] //#[ignore] fn turning_right_does_not_change_position() { let robot = Robot::new(0, 0, Direction::North).turn_right(); assert_eq!((0, 0), robot.position()); } #[test] //#[ignore] fn turning_right_from_north_points_the_robot_east() { let robot = Robot::new(0, 0, Direction::North).turn_right(); assert_eq!(&Direction::East, robot.direction()); } #[test] //#[ignore] fn turning_right_from_east_points_the_robot_south() { let robot = Robot::new(0, 0, Direction::East).turn_right(); assert_eq!(&Direction::South, robot.direction()); } #[test] //#[ignore] fn turning_right_from_south_points_the_robot_west() { let robot = Robot::new(0, 0, Direction::South).turn_right(); assert_eq!(&Direction::West, robot.direction()); } #[test] //#[ignore] fn turning_right_from_west_points_the_robot_north() { let robot = Robot::new(0, 0, Direction::West).turn_right(); assert_eq!(&Direction::North, robot.direction()); } #[test] //#[ignore] fn turning_left_does_not_change_position() { let robot = Robot::new(0, 0, Direction::North).turn_left(); assert_eq!((0, 0), robot.position()); } #[test] //#[ignore] fn turning_left_from_north_points_the_robot_west() { let robot = Robot::new(0, 0, Direction::North).turn_left(); assert_eq!(&Direction::West, robot.direction()); } #[test] //#[ignore] fn turning_left_from_west_points_the_robot_south() { let robot = Robot::new(0, 0, Direction::West).turn_left(); assert_eq!(&Direction::South, robot.direction()); } #[test] //#[ignore] fn turning_left_from_south_points_the_robot_east() { let robot = Robot::new(0, 0, Direction::South).turn_left(); assert_eq!(&Direction::East, robot.direction()); } #[test] //#[ignore] fn turning_left_from_east_points_the_robot_north() { let robot = Robot::new(0, 0, Direction::East).turn_left(); assert_eq!(&Direction::North, robot.direction()); } #[test] //#[ignore] fn advance_does_not_change_the_direction() { let robot = Robot::new(0, 0, Direction::North).advance(); assert_eq!(&Direction::North, robot.direction()); } #[test] //#[ignore] fn advance_increases_the_y_coordinate_by_one_when_facing_north() { let robot = Robot::new(0, 0, Direction::North).advance(); assert_eq!((0, 1), robot.position()); } #[test] //#[ignore] fn advance_decreases_the_y_coordinate_by_one_when_facing_south() { let robot = Robot::new(0, 0, Direction::South).advance(); assert_eq!((0, -1), robot.position()); } #[test] //#[ignore] fn advance_increases_the_x_coordinate_by_one_when_facing_east() { let robot = Robot::new(0, 0, Direction::East).advance(); assert_eq!((1, 0), robot.position()); } #[test] //#[ignore] fn advance_decreases_the_x_coordinate_by_one_when_facing_west() { let robot = Robot::new(0, 0, Direction::West).advance(); assert_eq!((-1, 0), robot.position()); } #[test] //#[ignore] fn follow_instructions_to_move_west_and_north() { let robot = Robot::new(0, 0, Direction::North).instructions("LAAARALA"); assert_eq!((-4, 1), robot.position()); assert_eq!(&Direction::West, robot.direction()); } #[test] //#[ignore] fn follow_instructions_to_move_west_and_south() { let robot = Robot::new(2, -7, Direction::East).instructions("RRAAAAALA"); assert_eq!((-3, -8), robot.position()); assert_eq!(&Direction::South, robot.direction()); } #[test] //#[ignore] fn follow_instructions_to_move_east_and_north() { let robot = Robot::new(8, 4, Direction::South).instructions("LAAARRRALLLL"); assert_eq!((11, 5), robot.position()); assert_eq!(&Direction::North, robot.direction()); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { #[derive(PartialEq, Debug, Copy, Clone)] pub enum Direction { North, East, South, West, } impl Direction { pub fn previous_clockwise(&self) -> Self { match *self { Direction::North => Direction::West, Direction::East => Direction::North, Direction::South => Direction::East, Direction::West => Direction::South, } } pub fn next_clockwise(&self) -> Self { match *self { Direction::North => Direction::East, Direction::East => Direction::South, Direction::South => Direction::West, Direction::West => Direction::North, } } } #[derive(Clone, Copy)] struct Position { x: i32, y: i32, } impl Position { fn new(x: i32, y: i32) -> Self { Position { x: x, y: y } } fn advance(&self, direction: &Direction) -> Self { match *direction { Direction::North => Self::new(self.x, self.y + 1), Direction::South => Self::new(self.x, self.y - 1), Direction::East => Self::new(self.x + 1, self.y), Direction::West => Self::new(self.x - 1, self.y), } } } #[derive(Clone)] pub struct Robot { position: Position, direction: Direction, } impl Robot { pub fn new(x: i32, y: i32, d: Direction) -> Self { Robot::build(Position::new(x, y), d) } fn build(position: Position, direction: Direction) -> Self { Robot { position: position, direction: direction, } } pub fn turn_right(&self) -> Self { Self::build(self.position, self.direction.next_clockwise()) } pub fn turn_left(&self) -> Self { Self::build(self.position, self.direction.previous_clockwise()) } pub fn advance(&self) -> Self { Self::build(self.position.advance(&self.direction), self.direction) } pub fn instructions(&self, instructions: &str) -> Self { instructions .chars() .fold(self.clone(), |robot, instruction| { robot.execute(instruction) }) } pub fn position(&self) -> (i32, i32) { (self.position.x, self.position.y) } pub fn direction(&self) -> &Direction { &self.direction } fn execute(self, command: char) -> Self { match command { 'R' => self.turn_right(), 'L' => self.turn_left(), 'A' => self.advance(), _ => self, } } } #}