/// A Robot *aka droid* is represented here. /// Each robot must have a unique id. pub struct Robot { id: i32, o: Orientation, p: Position, i: Vec, } impl Robot { /// Create new `Robot` with given id, `Orientation`, `Position` and instructions. fn new(id: i32, o: Orientation, p: Position, i: Vec) -> Robot { Robot { id, o, p, i } } /// Apply given instruction to a `Robot`. fn execute_instruction(&mut self) -> Result<(), &'static str> { match self.i.pop() { Some(instruction) => match instruction { 'L' => Ok(match self.o { Orientation::N => self.o = Orientation::W, Orientation::E => self.o = Orientation::N, Orientation::S => self.o = Orientation::E, Orientation::W => self.o = Orientation::S, }), 'R' => Ok(match self.o { Orientation::N => self.o = Orientation::E, Orientation::E => self.o = Orientation::S, Orientation::S => self.o = Orientation::W, Orientation::W => self.o = Orientation::N, }), 'F' => Ok(match self.o { Orientation::N => self.p.y += 1, Orientation::E => self.p.x += 1, Orientation::S => self.p.y -= 1, Orientation::W => self.p.x -= 1, }), _ => Err("Invalid instruction."), }, None => Ok(()), } } } /// Enum to store all possible orientations. enum Orientation { N, E, S, W, } /// Struct to store robot position. struct Position { x: i32, y: i32, } #[cfg(test)] mod tests { use super::*; #[test] fn test_new_robot() { let r: Robot = Robot::new( 0, Orientation::N, Position { x: 1, y: 2 }, vec!['L', 'L', 'F', 'R'], ); assert_eq!(r.id, 0); assert!(matches!(r.o, Orientation::N)); assert_eq!(r.p.x, 1); assert_eq!(r.p.y, 2); assert_eq!(r.i, vec!['L', 'L', 'F', 'R']); } #[test] fn test_execute_instruction() { let mut r: Robot = Robot::new( 0, Orientation::N, Position { x: 1, y: 2 }, vec!['R', 'L', 'F', 'F'], ); assert!(r.execute_instruction().is_ok()); assert_eq!(r.p.x, 1); assert_eq!(r.p.y, 3); } }