|
| 1 | +/** |
| 2 | + * [2069] Walking Robot Simulation II |
| 3 | + * |
| 4 | + * A width x height grid is on an XY-plane with the bottom-left cell at (0, 0) and the top-right cell at (width - 1, height - 1). The grid is aligned with the four cardinal directions ("North", "East", "South", and "West"). A robot is initially at cell (0, 0) facing direction "East". |
| 5 | + * The robot can be instructed to move for a specific number of steps. For each step, it does the following. |
| 6 | + * <ol> |
| 7 | + * Attempts to move forward one cell in the direction it is facing. |
| 8 | + * If the cell the robot is moving to is out of bounds, the robot instead turns 90 degrees counterclockwise and retries the step. |
| 9 | + * </ol> |
| 10 | + * After the robot finishes moving the number of steps required, it stops and awaits the next instruction. |
| 11 | + * Implement the Robot class: |
| 12 | + * |
| 13 | + * Robot(int width, int height) Initializes the width x height grid with the robot at (0, 0) facing "East". |
| 14 | + * void step(int num) Instructs the robot to move forward num steps. |
| 15 | + * int[] getPos() Returns the current cell the robot is at, as an array of length 2, [x, y]. |
| 16 | + * String getDir() Returns the current direction of the robot, "North", "East", "South", or "West". |
| 17 | + * |
| 18 | + * |
| 19 | + * Example 1: |
| 20 | + * <img alt="example-1" src="https://assets.leetcode.com/uploads/2021/10/09/example-1.png" style="width: 498px; height: 268px;" /> |
| 21 | + * Input |
| 22 | + * ["Robot", "step", "step", "getPos", "getDir", "step", "step", "step", "getPos", "getDir"] |
| 23 | + * [[6, 3], [2], [2], [], [], [2], [1], [4], [], []] |
| 24 | + * Output |
| 25 | + * [null, null, null, [4, 0], "East", null, null, null, [1, 2], "West"] |
| 26 | + * Explanation |
| 27 | + * Robot robot = new Robot(6, 3); // Initialize the grid and the robot at (0, 0) facing East. |
| 28 | + * robot.step(2); // It moves two steps East to (2, 0), and faces East. |
| 29 | + * robot.step(2); // It moves two steps East to (4, 0), and faces East. |
| 30 | + * robot.getPos(); // return [4, 0] |
| 31 | + * robot.getDir(); // return "East" |
| 32 | + * robot.step(2); // It moves one step East to (5, 0), and faces East. |
| 33 | + * // Moving the next step East would be out of bounds, so it turns and faces North. |
| 34 | + * // Then, it moves one step North to (5, 1), and faces North. |
| 35 | + * robot.step(1); // It moves one step North to (5, 2), and faces North (not West). |
| 36 | + * robot.step(4); // Moving the next step North would be out of bounds, so it turns and faces West. |
| 37 | + * // Then, it moves four steps West to (1, 2), and faces West. |
| 38 | + * robot.getPos(); // return [1, 2] |
| 39 | + * robot.getDir(); // return "West" |
| 40 | + * |
| 41 | + * |
| 42 | + * Constraints: |
| 43 | + * |
| 44 | + * 2 <= width, height <= 100 |
| 45 | + * 1 <= num <= 10^5 |
| 46 | + * At most 10^4 calls in total will be made to step, getPos, and getDir. |
| 47 | + * |
| 48 | + */ |
| 49 | +pub struct Solution {} |
| 50 | + |
| 51 | +// problem: https://leetcode.com/problems/walking-robot-simulation-ii/ |
| 52 | +// discuss: https://leetcode.com/problems/walking-robot-simulation-ii/discuss/?currentPage=1&orderBy=most_votes&query= |
| 53 | + |
| 54 | +// submission codes start here |
| 55 | + |
| 56 | +enum Direction { |
| 57 | + North, |
| 58 | + East, |
| 59 | + South, |
| 60 | + West, |
| 61 | +} |
| 62 | + |
| 63 | +struct Robot { |
| 64 | + max_x: i32, |
| 65 | + max_y: i32, |
| 66 | + current_route_num: i32, |
| 67 | + position_cache: (i32, i32, Direction), |
| 68 | +} |
| 69 | + |
| 70 | +/** |
| 71 | + * `&self` means the method takes an immutable reference. |
| 72 | + * If you need a mutable reference, change it to `&mut self` instead. |
| 73 | + */ |
| 74 | +impl Robot { |
| 75 | + fn new(width: i32, height: i32) -> Self { |
| 76 | + Self { |
| 77 | + max_x: width - 1, |
| 78 | + max_y: height - 1, |
| 79 | + current_route_num: -1, |
| 80 | + position_cache: (0, 0, Direction::East), |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + fn step(&mut self, num: i32) { |
| 85 | + if self.current_route_num < 0 { |
| 86 | + self.current_route_num = 0; |
| 87 | + } |
| 88 | + |
| 89 | + let perim = (self.max_x + 1) * 2 + (self.max_y - 1) * 2; |
| 90 | + |
| 91 | + self.current_route_num += num; |
| 92 | + self.current_route_num %= perim; |
| 93 | + self.set_position_data(); |
| 94 | + } |
| 95 | + |
| 96 | + fn get_pos(&self) -> Vec<i32> { |
| 97 | + vec![self.position_cache.0.clone(), self.position_cache.1.clone()] |
| 98 | + } |
| 99 | + |
| 100 | + fn get_dir(&self) -> String { |
| 101 | + match self.position_cache.2 { |
| 102 | + Direction::North => "North", |
| 103 | + Direction::East => "East", |
| 104 | + Direction::South => "South", |
| 105 | + Direction::West => "West", |
| 106 | + } |
| 107 | + .to_string() |
| 108 | + } |
| 109 | + |
| 110 | + fn set_position_data(&mut self) { |
| 111 | + self.position_cache = if self.current_route_num < 0 { |
| 112 | + (0, 0, Direction::East) |
| 113 | + } else if self.current_route_num == 0 { |
| 114 | + (self.current_route_num, 0, Direction::South) |
| 115 | + } else if self.current_route_num <= self.max_x { |
| 116 | + (self.current_route_num, 0, Direction::East) |
| 117 | + } else if self.current_route_num <= self.max_x + self.max_y { |
| 118 | + ( |
| 119 | + self.max_x, |
| 120 | + self.current_route_num - self.max_x, |
| 121 | + Direction::North, |
| 122 | + ) |
| 123 | + } else if self.current_route_num <= 2 * self.max_x + self.max_y { |
| 124 | + ( |
| 125 | + self.max_x - (self.current_route_num - self.max_x - self.max_y), |
| 126 | + self.max_y, |
| 127 | + Direction::West, |
| 128 | + ) |
| 129 | + } else { |
| 130 | + ( |
| 131 | + 0, |
| 132 | + self.max_y - (self.current_route_num - 2 * self.max_x - self.max_y), |
| 133 | + Direction::South, |
| 134 | + ) |
| 135 | + } |
| 136 | + } |
| 137 | +} |
| 138 | + |
| 139 | +/** |
| 140 | + * Your Robot object will be instantiated and called as such: |
| 141 | + * let obj = Robot::new(width, height); |
| 142 | + * obj.step(num); |
| 143 | + * let ret_2: Vec<i32> = obj.get_pos(); |
| 144 | + * let ret_3: String = obj.get_dir(); |
| 145 | + */ |
| 146 | + |
| 147 | +// submission codes end |
| 148 | + |
| 149 | +#[cfg(test)] |
| 150 | +mod tests { |
| 151 | + use super::*; |
| 152 | + |
| 153 | + #[test] |
| 154 | + fn test_2069_example_1() { |
| 155 | + let mut robot = Robot::new(6, 3); // Initialize the grid and the robot at (0, 0) facing East. |
| 156 | + robot.step(2); // It moves two steps East to (2, 0), and faces East. |
| 157 | + robot.step(2); // It moves two steps East to (4, 0), and faces East. |
| 158 | + assert_eq!(robot.get_pos(), vec![4, 0]); // return [4, 0] |
| 159 | + assert_eq!(robot.get_dir(), "East".to_string()); // return "East" |
| 160 | + robot.step(2); // It moves one step East to (5, 0), and faces East. |
| 161 | + // Moving the next step East would be out of bounds, so it turns and faces North. |
| 162 | + // Then, it moves one step North to (5, 1), and faces North. |
| 163 | + robot.step(1); // It moves one step North to (5, 2), and faces North (not West). |
| 164 | + robot.step(4); // Moving the next step North would be out of bounds, so it turns and faces West. |
| 165 | + // Then, it moves four steps West to (1, 2), and faces West. |
| 166 | + assert_eq!(robot.get_pos(), vec![1, 2]); // return [1, 2] |
| 167 | + assert_eq!(robot.get_dir(), "West".to_string()); // return "West" |
| 168 | + } |
| 169 | +} |
0 commit comments