/// <summary> /// Entry point for the Mars Rover processor /// </summary> /// <param name="text"></param> /// <returns></returns> public string Process(string text) { var result = new List<string>(); try { // Parse file content to a list of string (ignore LineFeed character) var fileContent = new List<string>(text.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)); // Validate general content: plateau, number of lines ... ValidatePlateauInformation(fileContent); var plateauCoordinate = fileContent[0].Split(' '); // Construct the plateau coordinates var thePlateau = new Coodinate { X = Convert.ToInt32(plateauCoordinate[0]), Y = Convert.ToInt32(plateauCoordinate[1]) }; // Process all rovers. If there's an error with a rover, it will be reported in the output then keep processing the next rover for (int lineNo = 1; lineNo < fileContent.Count; lineNo += 2) { result.Add(ProccessRoverMovement(thePlateau, fileContent, lineNo)); } } catch (InputFormatException inputFormatException) { result.Add(inputFormatException.Message); } return string.Join(Environment.NewLine, result.ToArray()); }
/// <summary> /// Ensure the rover's location doesn't fall out of the plateau /// </summary> /// <param name="plateauCoordinate"></param> public void ValidateLocation(Coodinate plateauCoordinate) { if ((plateauCoordinate.X < CurrentLocation.X) || (CurrentLocation.X < 0) || (plateauCoordinate.Y < CurrentLocation.Y) || (plateauCoordinate.Y < 0)) { throw new RoverLocationException("Rover location is out of the plateau"); } }
/// <summary> /// Contruct the rover object /// All information are already validated, so the construction is straightforward /// </summary> /// <param name="roverInformation"></param> /// <returns></returns> private Rover InitializeRover(string roverInformation) { var roverLocationInput = roverInformation.Split(' '); // Extract the initial location var roverLocation = new Coodinate { X = Convert.ToInt32(roverLocationInput[0]), Y = Convert.ToInt32(roverLocationInput[1]) }; var stateFactory = new DirectionFactory(); var direction = stateFactory.InitializeAllCardinalPoints(); // Extract the initial direction var roverFirstDirection = stateFactory.GetDirection(direction, roverLocationInput[2]); if (roverFirstDirection == null) return null; return new Rover { CurrentDirection = roverFirstDirection, CurrentLocation = roverLocation }; }
/// <summary> /// Walk through each command and change the rover's location and direction accordingly /// </summary> /// <param name="thePlateau"></param> /// <param name="fileContent"></param> /// <param name="lineNo"></param> /// <returns></returns> private string ProccessRoverMovement(Coodinate thePlateau, List<string> fileContent, int lineNo) { try { // Ensure all provided information for a rover is correct ValidateRoverInformation(fileContent, lineNo); // Construct a rover var theRover = InitializeRover(fileContent[lineNo]); if (theRover == null) { throw new InputFormatException("Cannot initialize the rover"); } // Ensure the rover doesn't fall out of plateau theRover.ValidateLocation(thePlateau); // Get the movement commands var roverMovementCommands = fileContent[lineNo + 1].ToCharArray(); foreach (var movement in roverMovementCommands) { switch (movement) { case 'L': theRover.TurnLeft(); break; case 'R': theRover.TurnRight(); break; case 'M': theRover.MoveForward(); break; } } // Ensure the rover doesn't fall out of plateau theRover.ValidateLocation(thePlateau); return string.Format("{0} {1} {2}", theRover.CurrentLocation.X, theRover.CurrentLocation.Y, theRover.CurrentDirection.Name); } catch (RoverLocationException roverLocationException) { return roverLocationException.Message; } }
public void MoveForward() { CurrentLocation = CurrentDirection.MoveForward(CurrentLocation); }