2023. 4. 2. 03:30ㆍALGORITHM/Swift
문제링크
문제설명
지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양의 공원에서 로봇 강아지가 산책을 하려합니다. 산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.
- ["방향 거리", "방향 거리" … ]
예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다. 로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.
- 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
- 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.
위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0), 우측 하단의 좌표는 (H - 1, W - 1) 입니다.
공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가 매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한사항
- 3 ≤ park의 길이 ≤ 50
- 3 ≤ park[i]의 길이 ≤ 50
- park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
- S : 시작 지점
- O : 이동 가능한 통로
- X : 장애물
- park는 직사각형 모양입니다.
- park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
- 1 ≤ routes의 길이 ≤ 50
- routes의 각 원소는 로봇 강아지가 수행할 명령어를 나타냅니다.
- 로봇 강아지는 routes의 첫 번째 원소부터 순서대로 명령을 수행합니다.
- routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
- op는 다음 네 가지중 하나로 이루어져 있습니다.
- N : 북쪽으로 주어진 칸만큼 이동합니다.
- S : 남쪽으로 주어진 칸만큼 이동합니다.
- W : 서쪽으로 주어진 칸만큼 이동합니다.
- E : 동쪽으로 주어진 칸만큼 이동합니다.
- 1 ≤ n ≤ 9
- op는 다음 네 가지중 하나로 이루어져 있습니다.
입출력 예
입출력 예 설명
입출력 예 #1
입력된 명령대로 동쪽으로 2칸, 남쪽으로 2칸, 서쪽으로 1칸 이동하면 [0,0] -> [0,2] -> [2,2] -> [2,1]이 됩니다.
입출력 예 #2
입력된 명령대로라면 동쪽으로 2칸, 남쪽으로 2칸, 서쪽으로 1칸 이동해야하지만 남쪽으로 2칸 이동할 때 장애물이 있는 칸을 지나기 때문에 해당 명령을 제외한 명령들만 따릅니다. 결과적으로는 [0,0] -> [0,2] -> [0,1]이 됩니다.
입출력 예 #3
처음 입력된 명령은 공원을 나가게 되고 두 번째로 입력된 명령 또한 장애물을 지나가게 되므로 두 입력은 제외한 세 번째 명령만 따르므로 결과는 다음과 같습니다. [0,1] -> [0,0]
분석
지나가는 길을 O, 장애물은 x로 나타낸 곳에 로봇 강아지가 산책을 한다.
주어진 방향으로 이동할 때 공원을 벗어나는 지 확인한다.
주어진 방향으로 이동 중 장애물을 만나는 지 확인한다.
위의 두가지 중 하나라도 해당된다면 해당 명령을 무시하고 다음을 수행한다.
수행할 명령이 주어졌을 때 로봇 강아지가 모든 명령을 수행한 후 놓인 위치를 리턴하는 문제
풀이 과정
길찾기 문제이고 가야할 방향을 정해주고 마지막으로 있는 위치를 출력한다.
먼저 park배열에 있는 공원의 map을 입력한다.
var map = Array(repeating: Array(repeating: "", count: w), count: h)
var robot = [0, 0]
for i in 0..<park.count {
map[i] = park[i].map { String($0) }
if let startIdx = map[i].firstIndex(of: "S") {
robot = [i, startIdx]
}
}
robot 은 현재 로봇강아지의 위치를 나타낸다.
var directions = [[String]]()
for i in 0..<routes.count {
directions.append(routes[i].split(separator: " ").map {String($0)})
}
다음으로는 가야할 방향과 칸 수를 배열에 넣는다.
문제에서 주어진 조건을 수행한다.
func isValid(y: Int, x: Int) -> Bool {
return 0 <= y && y < h && 0 <= x && x < w ? true : false
}
가로 세로의 길이에 벗어나는 지를 확인한다.
다음으로 이제 강아지가 다음으로 갈 위치를 정해주면 된다.
for i in 0..<directions.count {
var isNext = true
switch directions[i][0] {
case "E":
next = [robot[0], robot[1]+Int(directions[i][1])!]
if isValid(y: next[0], x: next[1]) {
for i in robot[1]...next[1] {
if map[next[0]][i] == "X" {
isNext = false
break
}
}
if isNext {
robot = next
}
}
...
}
}
E 동쪽으로 가는 것은 오른쪽으로 이동하기 때문에 로봇 강아지의 x좌표에 더해준다.
그리고 가로세로길이를 벗어나는지 확인 먼저 해준 후 현재 있는 위치부터 다음으로 갈 위치까지 장애물이 있는 지 확인한다.
이것을 따로 함수로 빼서 해주고 싶었는데 ... 하다가 범위가 고민되어서 그냥 isNext라는 변수를 빼서
장애물을 만나면 false로 지정해주고 true일 경우에만 로봇 강아지의 위치를 변경해주었다.
풀이
import Foundation
func solution(_ park:[String], _ routes:[String]) -> [Int] {
let w = park[0].count
let h = park.count
var map = Array(repeating: Array(repeating: "", count: w), count: h)
var robot = [0, 0]
var next = [0, 0]
func isValid(y: Int, x: Int) -> Bool {
return 0 <= y && y < h && 0 <= x && x < w ? true : false
}
for i in 0..<park.count {
map[i] = park[i].map { String($0) }
if let startIdx = map[i].firstIndex(of: "S") {
robot = [i, startIdx]
}
}
var directions = [[String]]()
for i in 0..<routes.count {
directions.append(routes[i].split(separator: " ").map {String($0)})
}
for i in 0..<directions.count {
var isNext = true
switch directions[i][0] {
case "E":
next = [robot[0], robot[1]+Int(directions[i][1])!]
if isValid(y: next[0], x: next[1]) {
for i in robot[1]...next[1] {
if map[next[0]][i] == "X" {
isNext = false
break
}
}
if isNext {
robot = next
}
}
case "W":
next = [robot[0], robot[1]-Int(directions[i][1])!]
if isValid(y: next[0], x: next[1]) {
for i in next[1]...robot[1] {
if map[next[0]][i] == "X" {
isNext = false
break
}
}
if isNext {
robot = next
}
}
case "S":
next = [robot[0]+Int(directions[i][1])!, robot[1]]
if isValid(y: next[0], x: next[1]) {
for i in robot[0]...next[0] {
if map[i][next[1]] == "X" {
isNext = false
break
}
}
if isNext {
robot = next
}
}
default:
next = [robot[0]-Int(directions[i][1])!, robot[1]]
if isValid(y: next[0], x: next[1]) {
for i in next[0]...robot[0] {
if map[i][next[1]] == "X" {
isNext = false
break
}
}
if isNext {
robot = next
}
}
}
}
return robot
}
결과
print(solution(["SOO","OOO","OOO"], ["E 2","S 2","W 1"]))
입출력 예시에서 routes가 다 같은 줄 알고 park만 변경해서 출력해줬는 데 결과가 다르게 나와서 내 코드가 틀린 줄 알았는데 그냥 routes를 변경해주지 않았던 것이었다... 이거때문에 10분은 쓴거같다...
입출력 예시를 잘 작성해서 결과를 확인하자...
📂 정리
길찾기 문제이긴 한데 평소에 백준에서 푸는 길찾기 문제와는 조금 다른 느낌이었다.
처음에는 그냥 장애물이 있는 곳으로 가면 안되는 줄 알고 풀었다가 자꾸 답이 이상해서 다시 확인했더니 가다가 중간에 장애물이 있을 경우에는 못가는 문제였다.
이걸 마지막에 알아서 시간이 좀 더 소요되었던 거 같다.
문제를 똑바로 안읽은 내 탓이겠지 ㅎㅎ
'ALGORITHM > Swift' 카테고리의 다른 글
[알고리즘] Swift -프로그래머스 연습문제 #120956(옹알이(1)) (0) | 2023.04.04 |
---|---|
[알고리즘] Swift -프로그래머스 연습문제 #172927(광물 캐기) (0) | 2023.04.04 |
[알고리즘] Swift -프로그래머스 연습문제 #176963(추억 점수) (0) | 2023.04.01 |
[알고리즘] Swift -백준 #11727(2×n 타일링 2) -DP (0) | 2023.03.27 |
[알고리즘] Swift -백준 #2193(이친수) -DP (0) | 2023.03.23 |