/// <param name="w">Plateau's width</param> /// <param name="h">Plateau's height</param> public Rover(int x, int y, Utils.Orientation orientation, RoverCommands nav, int w, int h) { this.Commands = nav ?? throw new ArgumentNullException(nameof(nav)); this.w = w; this.h = h; this.StartingState = new RoverState(x, y, orientation); this.CurrentState = this.StartingState.Clone(); StateHistory.Add(this.CurrentState); }
/// <summary>Parse a string of L R and M into a list of commands</summary> /// <returns>I like the TryParse pattern, I think it fits here</returns> public static bool TryParse(string input, out RoverCommands nav) { nav = default; if (string.IsNullOrWhiteSpace(input)) { throw new ArgumentNullException(input); } var lst = new List <Utils.Command>(); foreach (var chr in input.Trim().ToUpperInvariant().ToCharArray()) { switch (chr) { case 'L': lst.Add(Utils.Command.Left); break; case 'R': lst.Add(Utils.Command.Right); break; case 'M': lst.Add(Utils.Command.Move); break; default: return(false); } } if (lst.Count == 0) { return(false); } nav = new RoverCommands(lst); return(true); }
/// <summary> /// Split the input into lines and process according to spec /// </summary> /// <returns>grid width and height and rovers preloaded with nav paths</returns> /// <remarks> /// Test Input: /// 5 5 /// 1 2 N /// LMLMLMLMM /// 3 3 E /// MMRMMRMRRM /// Expected Output: /// 1 3 N /// 5 1 E /// </remarks> public static (int gridWidth, int gridHeight, Rovers rovers) ProcessInput(string text) { if (string.IsNullOrWhiteSpace(text)) { throw new ArgumentNullException(nameof(text)); } var lines = text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); if (lines.Length == 0) { throw new ArgumentException("invalid format, no lines found", nameof(text)); } var splits = lines[0].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (splits.Length != 2) { throw new Exception("invalid format - first line, should have 2 numbers"); } if (!int.TryParse(splits[0], out int w) || w <= 0) { throw new Exception("invalid format - first line, should have 2 numbers, first part was not a >0 integer"); } if (!int.TryParse(splits[1], out int h) || h <= 0) { throw new Exception("invalid format - first line, should have 2 numbers, second part was not a >0 integer"); } if (lines.Length > 2) { var lst = new List <Rover>(); for (int i = 1; i < lines.Length; i += 2) { if (char.IsDigit(lines[i][0])) { //current line is the starting coordinate of a rover since it's starting with a number splits = lines[i].Split(' '); if (splits.Length < 3 || !int.TryParse(splits[0], out int x) || !int.TryParse(splits[1], out int y) || !Utils.OrientationTryParse(splits[2], out Utils.Orientation orientation)) { throw new Exception("invalid format line: " + i); } if (x < 0 || x > w || y < 0 || y > h) { throw new Exception("invalid position, outside the bounds"); } if (i < lines.Length - 1) { //nav points must be on the next line if (!RoverCommands.TryParse(lines[i + 1], out RoverCommands nav)) { throw new Exception("invalid format line: " + i + 1); } lst.Add(new Rover(x, y, orientation, nav, w, h)); } } } return(w, h, new Rovers(lst)); } return(w, h, null); }