2024. 4. 8. 18:30ㆍ개발자 과정/Kotlin
https://n-pureun.tistory.com/62
(코딩테스트) 공원산책
https://school.programmers.co.kr/learn/courses/30/lessons/172928 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞
n-pureun.tistory.com
문제는 이전에 c/c++로 푼 이력이 있으나, 그때당시 구현하려 했던 로직을 구현하지 못했던 바
코틀린을 배우면서 다시 풀어 보았다.
풀이의 선택과정
1. 시작좌표를 찾는다. 이것은 함수로 빼낸다.
2. 이전에 문제를 풀 때 하고싶었던 로직인데, map을 추가해서 if나 when으로 분기를
만드는 것이 아닌, key 매칭으로 알아서 계산하게 할 것이다.
3. 알아서 계산하면 난 문제에서 요구하는 조건문만 걸어주면 된다.
4. dfs의 방식을 조금 따왔는데,현재 좌표를 백업해놓고, 조건에 안맞으면 데이터를 날리는
로직을 만들 것이다.
근데 결과값이 이상하다.
코드가 길어 오류풀이는 문제 있는 부분만 올린다.
오류 풀이
var backUp = answer
for (i in routes.indices) {
var isFail = false
for (j in 0 until routes[i].last().digitToInt()) {
answer[0] += m[routes[i].first()]!!.first
answer[1] += m[routes[i].first()]!!.second
if (!(answer[0] in park.indices && answer[1] in park[answer[0]].indices
&& park[answer[0]][answer[1]] != 'X')) {
isFail = true
break
}
}
if (isFail) answer = backUp
else backUp=answer
}
return answer
= 로직만 보면 맞아야 하는데, 값이 이상하게 나온다.
원인
객체 자체를 넘겨주었다.
= 내가 변수에 인자를 넘겨줄때, 객체 그 자체(주소)를 넘겨주었기에, 넘겨받은 변수에서
값을 바꾸면 원본변수도 값이 바뀌고, 그 반대 상황도 일어나며 뒤죽박죽이 되버린 것이다.
이를 회피하기 위해서 변수를 새로 할당해 넣어줘야 하는데,
intArratOf로 전부 넣으려 하니, 코드가 지저분해 져서 다른 방법은 없나 찾아 보았다.
해결방안
.copyOf()
= 해당 함수를 쓰면 복사된 객체를 리턴해 준다고 한다.
그렇다면 메모리 주소가 서로 다르기에 값을 바꿔도 각각의 변수는
데이터를 보존할 수 있게 되고, 따로 할당해서 넣는 것보다 코드가 깔끔해진다.
정답풀이
class Solution {
private fun findStartPoint(park: Array<String>):IntArray
{
val now= IntArray(2){0}
for(i in park.indices)
{
if(park[i].indexOf("S")!=-1) {
now[0]=i
now[1] = park[i].indexOf("S")
break
}
}
return now
}
fun solution(park: Array<String>, routes: Array<String>): IntArray {
var answer = findStartPoint(park)
val m = mapOf<Char, Pair<Int, Int>>(
'N' to Pair(-1, 0),
'S' to Pair(1, 0),
'W' to Pair(0, -1),
'E' to Pair(0, 1),
)
val st = ArrayDeque<IntArray>().apply { add(answer.copyOf()) }
for (i in routes.indices) {
var isFail = false
for (j in 0 until routes[i].last().digitToInt()) {
answer[0] += m[routes[i].first()]!!.first
answer[1] += m[routes[i].first()]!!.second
if (!(answer[0] in park.indices && answer[1] in park[answer[0]].indices
&& park[answer[0]][answer[1]] != 'X')
) {
isFail = true
break
}
}
if (isFail) answer = st.last().copyOf()
else st.add(answer.copyOf())
}
return answer
}
}
핵심로직
val m = mapOf<Char, Pair<Int, Int>>(
'N' to Pair(-1, 0),
'S' to Pair(1, 0),
'W' to Pair(0, -1),
'E' to Pair(0, 1),
)
= 미리 map에 문제에 맞는 값을 지정해 놓고 단순 +연산으로 if, when문을 없앨 수 있다.
for (j in 0 until routes[i].last().digitToInt()) {
answer[0] += m[routes[i].first()]!!.first
answer[1] += m[routes[i].first()]!!.second
if (!(answer[0] in park.indices && answer[1] in park[answer[0]].indices
&& park[answer[0]][answer[1]] != 'X')) {
isFail = true
break
}
}
= !!는 null이 아니라는 보장을 하는 표현법이라고 한다. routes[i]의 첫글자는 미리 할당된 map의 key값이 되고,
+연산만으로 좌표가 수정된다. 그 후 해당 좌표가 배열안에 들어 가는지, "X"가 아닌지를 판별한다.
if문의 순서에 주의해야 하는데, if의 논리연산은 ->방향이다. 그러므로 큰 조건부터 들어가야 한다.
1차원 배열(i) 안에 들어가는지 -> 2차원 배열안에(j)안에 들어가는지 -> 두 조건 모두 충족되면 그 좌표는 'X'를 가리키는지.
새로 알게된 것
변수를 복사할땐 .copyOf()를 쓰자!
= 그리고 내가 풀고자 했던 방법으로 풀게 되어서 기분이 좋다.
'개발자 과정 > Kotlin' 카테고리의 다른 글
(코딩테스트) 2016년 (LocalDate) (0) | 2024.04.11 |
---|---|
(코딩테스트) 명예의 전당(1) (우선순위 큐) (0) | 2024.04.11 |
(코딩테스트) 콜라 문제 (0) | 2024.04.08 |
(코딩테스트)푸드 파이트 대회 (repeat()) (0) | 2024.04.04 |
(코딩테스트)가장 가까운 같은 글자 (0) | 2024.04.03 |