문제
지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양의 공원에서 로봇 강아지가 산책을 하려합니다. 산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.
- ["방향 거리", "방향 거리" … ]
예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다. 로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.
- 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
- 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.
위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0), 우측 하단의 좌표는 (H - 1, W - 1) 입니다.
공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가 매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한사항
park
- park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
- S : 시작 지점
- O : 이동 가능한 통로
- X : 장애물
- 직사각형 모양입니다.
routes
- 첫 번째 원소부터 순서대로 명령을 수행합니다.
- routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
- op 이동할 방향
- N : 북쪽으로 주어진 칸만큼 이동합니다.
- S : 남쪽으로 주어진 칸만큼 이동합니다.
- W : 서쪽으로 주어진 칸만큼 이동합니다.
- E : 동쪽으로 주어진 칸만큼 이동합니다.
입출력 예시
입출력 예 #1
- 입력
- park: ["SOO","OOO","OOO"]
- routes: ["E 2","S 2","W 1"]
- 출력: [2,1]
입출력 예 #2
- 입력
- park: ["SOO","OXX","OOO"]
- routes: ["E 2","S 2","W 1"]
- 출력: [0,1]
입출력 예 #3
- 입력
- park: ["OSO","OOO","OXO","OOO"]
- routes: ["E 2","S 3","W 1"]
- 출력: [0,0]
코드 1. 바둑판 그리기
class Solution {
companion object {
private const val START = 'S'
private const val BLOCK = 'X'
private const val ROAD = 'O'
}
fun solution(park: Array<String>, routes: Array<String>): IntArray {
// 로봇 위치
var robot = Pair(0, 0)
// 공원 바둑판 그리기
val row = park.first().length
val col = park.count()
val board = Array(row) { Array(col) { ROAD } }
park.forEachIndexed { y, str ->
for (x in str.indices) {
board[x][y] = str[x]
if (str[x] == START) robot = Pair(x, y)
}
}
// 로봇 강아지 이동
routes.forEach { route ->
var nextX = robot.first
var nextY = robot.second
val (direction, distance) = route.split(" ")
when (direction) {
"E" -> nextX += distance.toInt() * 1
"W" -> nextX += distance.toInt() * -1
"N" -> nextY += distance.toInt() * -1
"S" -> nextY += distance.toInt() * 1
}
// 장외
if (nextX < 0 || nextY < 0) return@forEach
if (nextX >= row || nextY >= col) return@forEach
// 가는 길 장애물
for (i in minOf(robot.first, nextX)..maxOf(robot.first, nextX)) {
for (j in minOf(robot.second, nextY)..maxOf(robot.second, nextY)) {
if (board[i][j] == BLOCK) return@forEach
}
}
// 이동
robot = Pair(nextX, nextY)
}
return intArrayOf(robot.second, robot.first)
}
}
테스트 1 〉 통과 (32.82ms, 63.3MB)
테스트 2 〉 통과 (21.73ms, 63.4MB)
테스트 3 〉 통과 (21.69ms, 63.8MB)
테스트 4 〉 통과 (29.60ms, 64MB)
테스트 5 〉 통과 (26.18ms, 64.4MB)
테스트 6 〉 통과 (32.12ms, 64.8MB)
테스트 7 〉 통과 (22.05ms, 64.1MB)
테스트 8 〉 통과 (22.59ms, 64.2MB)
테스트 9 〉 통과 (32.01ms, 64.2MB)
테스트 10 〉 통과 (21.94ms, 64.3MB)
테스트 11 〉 통과 (25.77ms, 64.6MB)
테스트 12 〉 통과 (32.53ms, 64.3MB)
테스트 13 〉 통과 (22.58ms, 64.2MB)
테스트 14 〉 통과 (24.18ms, 64.1MB)
테스트 15 〉 통과 (21.78ms, 64.6MB)
테스트 16 〉 통과 (23.61ms, 64.3MB)
테스트 17 〉 통과 (21.59ms, 64.1MB)
테스트 18 〉 통과 (27.57ms, 63.9MB)
테스트 19 〉 통과 (22.33ms, 63.9MB)
테스트 20 〉 통과 (22.08ms, 64.1MB)
코드 2. 바둑판 그리지 않기
class Solution {
fun solution(park: Array<String>, routes: Array<String>): IntArray {
var answer = intArrayOf(0, 0)
// 이동 칸
val directionMove = hashMapOf(
"E" to intArrayOf(0, 1),
"W" to intArrayOf(0, -1),
"S" to intArrayOf(1, 0),
"N" to intArrayOf(-1, 0)
)
// 초기 위치
// forEach, forEachIndex는 반복적인 람다 호출로 퍼포먼스가 저하될 수 있기 때문에 for문 사용
for (y in park.indices) {
for (x in park[y].indices) {
if (park[y][x] == 'S') answer = intArrayOf(y, x)
}
}
// 이동
routes.forEach { route ->
val (direction, distance) = route.split(" ")
val move = directionMove[direction]!!
val step = distance.toInt()
var y = answer[0]
var x = answer[1]
for (i in 0 until step) {
y += move[0]
x += move[1]
// park.first() 보다 park[0]가 속도가 빠르다.
if (y < 0 || x < 0 || x >= park[0].length || y >= park.size || park[y][x] == 'X') {
y = answer[0]
x = answer[1]
break
}
}
answer = intArrayOf(y, x)
}
return answer
}
}
테스트 1 〉 통과 (12.59ms, 61.6MB)
테스트 2 〉 통과 (9.49ms, 60.9MB)
테스트 3 〉 통과 (10.07ms, 61.7MB)
테스트 4 〉 통과 (10.52ms, 59.9MB)
테스트 5 〉 통과 (9.65ms, 61.7MB)
테스트 6 〉 통과 (10.82ms, 61.3MB)
테스트 7 〉 통과 (14.11ms, 60.4MB)
테스트 8 〉 통과 (10.55ms, 60.7MB)
테스트 9 〉 통과 (12.02ms, 61.4MB)
테스트 10 〉 통과 (14.19ms, 61MB)
테스트 11 〉 통과 (14.31ms, 61.4MB)
테스트 12 〉 통과 (9.11ms, 61.3MB)
테스트 13 〉 통과 (14.19ms, 62.1MB)
테스트 14 〉 통과 (14.02ms, 61.8MB)
테스트 15 〉 통과 (9.50ms, 61.4MB)
테스트 16 〉 통과 (11.62ms, 61.4MB)
테스트 17 〉 통과 (10.33ms, 60.9MB)
테스트 18 〉 통과 (10.75ms, 60.6MB)
테스트 19 〉 통과 (10.01ms, 61.1MB)
테스트 20 〉 통과 (11.82ms, 61.2MB)