[LeetCode] 1041. Robot Bounded In Circle
===
###### tags: `LeetCode`
## 題目
On an infinite plane, a robot initially stands at `(0, 0)` and faces north. The robot can receive one of three instructions:
- `"G"`: go straight 1 unit;
- `"L"`: turn 90 degrees to the left;
- `"R"`: turn 90 degrees to the right.
The robot performs the `instructions` given in order, and repeats them forever.
Return `true` if and only if there exists a circle in the plane such that the robot never leaves the circle.
**Example 1:**
```
Input: instructions = "GGLLGG"
Output: true
Explanation: The robot moves from (0,0) to (0,2), turns 180 degrees, and then returns to (0,0).
When repeating these instructions, the robot remains in the circle of radius 2 centered at the origin.
```
**Example 2:**
```
Input: instructions = "GG"
Output: false
Explanation: The robot moves north indefinitely.
```
**Example 3:**
```
Input: instructions = "GL"
Output: true
Explanation: The robot moves from (0, 0) -> (0, 1) -> (-1, 1) -> (-1, 0) -> (0, 0) -> ...
```
**Constraints:**
- `1 <= instructions.length <= 100`
- `instructions[i]` is `'G'`, `'L'` or, `'R'`.
### 第一版
做法:
先想辦法走到底,再判斷是否能走回原點
```=Java
class Solution {
enum class Direction(val face: Int, val x: Int, val y: Int){
// face 為面向的方位
// 方位順序:N(0) -> E(1) -> S(2) -> W(3) -> N(0) -> ...
// 右轉('R') = 方位 + 1,左轉('L') = 方位 - 1
NORTH(0, 0, 1),
EAST(1, 1, 0),
SOUTH(2, 0, -1),
WEST(3, -1, 0)
}
companion object {
private const val STRAIGHT = 'G'
private const val LEFT = 'L'
private const val RIGHT = 'R'
private const val DIRECTION_COUNT = 4
}
fun isRobotBounded(instructions: String): Boolean {
// 初始位置
var tmpFace = Direction.NORTH
var tmpX = 0
var tmpY = 0
// TODO 可以先移除 "RRRR" & "LLLL"
// 先想辦法走到底
// 再判斷是否能走回原點
// 先走完整個 instructions
instructions.forEach {
when (it) {
STRAIGHT -> {
tmpX += tmpFace.x
tmpY += tmpFace.y
}
LEFT -> {
// 新的方向
var newFace = tmpFace.face - 1
if (newFace < 0) {
newFace += DIRECTION_COUNT
}
tmpFace = transToDirection(newFace)
}
RIGHT -> {
var newFace = tmpFace.face + 1
if (newFace >= DIRECTION_COUNT) {
newFace -= DIRECTION_COUNT
}
tmpFace = transToDirection(newFace)
}
}
}
// println(tmpFace.face)
// println("x: $tmpX, y: $tmpY")
// 判斷是否能回到原點
// 回到原點
if (tmpX == 0 && tmpY == 0) {
return true
}
if (tmpFace == Direction.NORTH) {
return false
}
return true
}
fun transToDirection(currentFace: Int): Direction {
return when (currentFace) {
Direction.NORTH.face -> Direction.NORTH
Direction.EAST.face -> Direction.EAST
Direction.SOUTH.face -> Direction.SOUTH
else -> Direction.WEST
}
}
}
```
**Success**
[Details](https://leetcode.com/submissions/detail/621408508/)
Runtime: 224 ms, faster than 43.24% of Kotlin online submissions for Robot Bounded In Circle.
Memory Usage: 33.8 MB, less than 70.95% of Kotlin online submissions for Robot Bounded In Circle.
---
### 第二版
試圖縮短時間
若遇到連續轉方向,一併判斷
```=Java
class Solution {
enum class Direction(val face: Int, val x: Int, val y: Int){
NORTH(0, 0, 1),
EAST(1, 1, 0),
SOUTH(2, 0, -1),
WEST(3, -1, 0)
}
companion object {
private const val STRAIGHT = 'G'
private const val LEFT = 'L'
private const val RIGHT = 'R'
private const val DIRECTION_COUNT = 4
}
fun isRobotBounded(instructions: String): Boolean {
// 初始位置
var tmpFace = Direction.NORTH
var tmpX = 0
var tmpY = 0
// 先想辦法走到底
// 再判斷是否能走回原點
// 先走完整個 instructions
// note:
// for (i in 0 until instructions.length) {}
// 因為 i cannot be reassigned
// 所以改成 var i 的方式
// end note
var i = 0
while (i < instructions.length) {
// 計算有連續幾個直走
var count = 0
for (j in i until instructions.length) {
if (instructions[j] == STRAIGHT) {
count++
} else {
break
}
}
if (count != 0) {
tmpX += tmpFace.x * count
tmpY += tmpFace.y * count
i += count
continue
}
// 計算有連續幾個轉向
count = 0
for (j in i until instructions.length) {
if (instructions[j] != STRAIGHT) {
count++
} else {
break
}
}
var faceSum = 0
for (j in i until i + count) {
if (instructions[j] == LEFT) {
faceSum--
} else {
faceSum++
}
}
i += count
if (faceSum % DIRECTION_COUNT == 0) {// 沒旋轉
continue
}
// 旋轉目前的方位
var newFace = (tmpFace.face + faceSum) % DIRECTION_COUNT
if (newFace < 0) {
newFace += DIRECTION_COUNT
}
tmpFace = transToDirection(newFace)
}
// println("f: ${tmpFace.face} ($tmpX, $tmpY)")
// 判斷是否能回到原點
// 回到原點
if (tmpX == 0 && tmpY == 0) {
return true
}
if (tmpFace == Direction.NORTH) {
return false
}
return true
}
fun transToDirection(currentFace: Int): Direction {
return when (currentFace) {
Direction.NORTH.face -> Direction.NORTH
Direction.EAST.face -> Direction.EAST
Direction.SOUTH.face -> Direction.SOUTH
else -> Direction.WEST
}
}
}
```
**Success**
[Details](https://leetcode.com/submissions/detail/621445613/)
Runtime: 200 ms, faster than 60.13% of Kotlin online submissions for Robot Bounded In Circle.
Memory Usage: 34.5 MB, less than 29.73% of Kotlin online submissions for Robot Bounded In Circle.