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,
       }
   }
}

#}



填充/相关