[프로그래머스] 공원 산책

neoneoneo·2024년 3월 28일
0

kotlin

목록 보기
44/49
post-custom-banner

문제 분석

공원 산책

요약 | 공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가 매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로 배열에 담아 return 하라

  • 강아지는 X표시 되어있는 장애물을 지나갈 수 없다.
  • 강아지는 park 바깥으로 나갈 수 없다.

Input data :

  • park: Array<String>
    • 3 ≤ park의 길이 ≤ 50
    • 3 ≤ park[i]의 길이 ≤ 50
    • park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
      • S : 시작 지점
      • O : 이동 가능한 통로
      • X : 장애물
    • park는 직사각형 모양입니다.
  • routes: Array<String>
    • 1 ≤ routes의 길이 ≤ 50
    • routes의 각 원소는 로봇 강아지가 수행할 명령어를 나타냅니다.
    • 로봇 강아지는 routes의 첫 번째 원소부터 순서대로 명령을 수행합니다.
    • routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
    • op는 다음 네 가지중 하나로 이루어져 있습니다.
      • N : 북쪽으로 주어진 칸만큼 이동합니다.
      • S : 남쪽으로 주어진 칸만큼 이동합니다.
      • W : 서쪽으로 주어진 칸만큼 이동합니다.
      • E : 동쪽으로 주어진 칸만큼 이동합니다.
    • 1 ≤ n ≤ 9

북, 서쪽으로 이동할 경우에는 park의 음수 인덱스로 가지 못하도록 유의해야하며, 남, 동쪽으로 이동할 경우에는 park에서 주어지는 string의 length, park의 size를 넘어가는 인덱스로 가지 못하도록 유의해야 한다.
주어지는 데이터의 크기가 아주 크지는 않으므로 자료 구조에 따라 속도 차이가 아주 크지는 않을 것 같다.

Output data :

IntArray

풀이

전개 순서

  1. 강아지의 시작점을 별도의 array(site)에 먼저 저장해둔다.
  • site에는 강아지의 이동 지점이 갱신된다.
  1. 강아지가 수행할 명령 목록(routes)를 순회하면서
  2. 이동 방향을 먼저 탐지하고
  3. 동쪽(E)일 경우
    4-1. 동쪽으로 이동할 칸 수(tempEW)를 저장해둔다.
    4-2. 이동할 칸 수가 공원 열 크기(maxE)를 벗어나면 해당 명령을 무시한다.
    4-3. 벗어나지 않으면 현재 의 각 열을 하나씩 순회하면서 강아지가 있는 현재 행(site[0])에 장애물(X)이 있는지 찾는다.
    4-4. 장애물이 탐지되었고, 해당 장애물의 위치가 이동할 칸 수(tempEW)보다 작다면 이동하지 못함을 저장해둔다(moveOrNot).
    4-5. 현재 행의 마지막 열에 접근했을 때, 이동할 수 있는 상태(moveOrNot = true)라면 강아지를 이동시킨다.
  4. 서쪽(W)일 경우에도 동쪽일 때와 마찬가지로 처리하되
  • 이동할 칸 수가 0보다 작을 경우(음수의 인덱스) 해당 명령을 무시한다.
  • 탐지된 장애물의 위치가 이동할 칸수보다 클 경우 이동하지 못함을 저장해두고 처리한다.
  1. 남쪽(S)일 경우
    6-1. 남쪽으로 이동할 칸 수(tempSN)을 저장해둔다.
    6-2. 이동할 칸 수가 공원 행 크기(maxS)를 벗어나면 해당 명령을 무시한다.
    6-3. 벗어나지 않으면 현재 의 각 행을 하나씩 순회하면서 강아지가 있는 현재 열(site[1])에 장애물이 있는지 찾는다.
    6-4. 장애물이 탐지되었고, 해당 장애물의 위치가 이동할 칸 수(tempSN)보다 작다면 이동하지 못함을 저장해둔다(moveOrNot).
    6-5. 현재 열의 마지막 행에 접근했을 때, 이동할 수 있는 상태(moveOrNot = true)라면 강아지를 이동시킨다.
  2. 북쪽(N)일 경우에도 남쪽일 때와 마찬가지로 처리하되
  • 이동할 칸 수가 0보다 작을 경우(음수의 인덱스) 해당 명령을 무시한다.
  • 탐지된 장애물의 위치가 이동할 칸수보다 클 경우 이동하지 못함을 저장해두고 처리한다.

코드

class Solution {
    fun solution(park: Array<String>, routes: Array<String>): IntArray {
        val maxS = park.size - 1
        val maxE = park[0].length - 1
        var site = intArrayOf(0, 0)        
        //시작점 찾기
        park.forEachIndexed { idxR, row ->
            row.forEachIndexed { idxC, column ->
                if(column == 'S') {
                    site = intArrayOf(idxR, idxC)
                }
            }
        }        
        //방향 거리 잡기
        routes.forEach {            
            when(it.first()) {
                'E' -> {
                    val tempEW = site[1] + it.last().toInt() - '0'.toInt()                    
                    if (tempEW > maxE) {
                        println("!!공원을 벗어납니다. 조건을 무시해야합니다.")
                    }                    
                    else {   
                        var moveOrNot = true
                        for (i in site[1] .. maxE) {
                            if (park[site[0]][i] == 'X') {
                                if (tempEW >= i) {
                                    moveOrNot = false
                                }
                            }
                            if (i == maxS && moveOrNot) {
                                site = intArrayOf(site[0], tempEW)
                            }
                        }
                    }
                }
                'W' -> {
                    val tempEW = site[1] - it.last().toInt() + '0'.toInt()
                    if (tempEW < 0) {
                        println("!!공원을 벗어납니다. 조건을 무시해야합니다.")
                    }
                    else {
                        var moveOrNot = true
                        for (i in 0 .. site[1]) {
                            if (park[site[0]][i] == 'X') {
                                if (tempEW <= i) {
                                    moveOrNot = false
                                }
                            }
                            if (i == site[1] && moveOrNot) {
                                site = intArrayOf(site[0], tempEW)
                            }
                        }
                    }
                }
                'S' -> {
                    val tempSN = site[0] + it.last().toInt() - '0'.toInt()                    
                    if (tempSN > maxS) {
                        println("!!공원을 벗어납니다. 조건을 무시해야합니다.")
                    } 
                    else {                        
                        var moveOrNot = true
                        for (i in site[0] .. maxS) {
                            if (park[i][site[1]] == 'X') {
                                if (tempSN >= i) {
                                    moveOrNot = false
                                }
                            }
                            if (i == maxS && moveOrNot) {
                                site = intArrayOf(tempSN, site[1])
                            }
                        }
                    }    
                }
                'N' -> {
                    val tempSN = site[0] - it.last().toInt() + '0'.toInt()
                    if (tempSN < 0) {
                        println("!!공원을 벗어납니다. 조건을 무시해야합니다.")
                    } 
                    else {
                        var moveOrNot = true
                        for (i in 0 .. site[0]) {
                            if (park[i][site[1]] == 'X') {
                                if (tempSN <= i) {
                                    moveOrNot = false
                                }
                            }
                            if (i == site[0] && moveOrNot) {
                                site = intArrayOf(tempSN, site[1])
                            }
                        }
                    }
                }
            }
        }                
        return site
    }
}

[TIL-240328]

post-custom-banner

0개의 댓글