[깃허브]
https://github.com/heesoo-park/ForCodeKata/tree/main/%EA%B4%91%EB%AC%BC%20%EC%BA%90%EA%B8%B0
[프로그래머스]
https://school.programmers.co.kr/learn/courses/30/lessons/172927
이전에 한번 풀려고 했다가 중도하차한 다음에 오늘 다시 도전했다.
그 때보다는 확실히 몸이 좋아서 그런지 문제에 집중이 잘 됐다.
물론 그렇다고 쉽게 풀린 건 아니었다.
가장 먼저 한 것은 입력으로 들어온 광물들을 Int타입으로 바꾸고 5개씩 나누는 작업을 했다.
그걸 위해서 key가 String이고 value가 Int인 해쉬맵을 만들어 map 안에서 사용했고 chunked 함수를 통해 5개씩 나눠주었다.
그랬더니 List<List<Int?>> 타입이 되었다.
그리고 해당 리스트를 순회하면서 가장 작은 값, 다이아몬드 > 철 > 돌 순으로 찾아 피로도를 계산해주었다.
다이아몬드가 있을 때는 다이아몬드 곡괭이 > 철 곡괭이 > 돌 곡괭이 순으로,
철과 돌만 있을 때는 철 곡괭이 > 다이아몬드 곡괭이 > 돌 곡괭이 순으로,
돌만 있을 때는 돌 곡괭이 > 철 곡괭이 > 다이아몬드 곡괭이 순으로
사용할 수 있게 세팅했다.
피로도 계산은 sumOf를 사용했고 그 안에서 문제에서 주어진 표를 변수로 만든 걸 가지고 곡괭이에 맞는 광물의 피로도를 변환해줬다.
이렇게 하고 제출했더니 틀렸다.
사실 제출할 때부터 틀릴 걸 직감했었다.
왜냐하면 내가 짠 알고리즘은 앞에서 뒤로 가는 단방향이었기 때문이다.
중간에 더 좋은 곡괭이를 써야하는 케이스를 커버하지 못하기 때문이다.
이걸 틀리고나서부터 고민하기 시작했다...ㅎㅎ
그래서 나온 건 광물들을 캘 수 있는 만큼만 잘라서 가지고 있고 조건에 맞춰서 정렬하자는 거였다.
어짜피 앞에서부터 차례대로만 광물을 가져갈 수 있는데 모든 광물들을 5개씩 잘라서 저장해놓을 필요가 없는거였다.
곡괭이의 개수만큼만 챙겼다.
물론 이 부분에서 런타임에러가 생겼었는데 이건 곡괭이가 잘라놓은 광물들의 개수보다 커서 그런 거였다.
그건 let 스코프 함수를 이용해 현재 광물들의 개수와 비교한 후 자르는 범위를 정하는 것으로 해결했다.
이제 쓸 것만 남았으니 마음대로 리스트를 움직여도 괜찮았다.
더욱이 다이아몬드, 철, 돌 곡괭이 순으로 사용할 수 있게 정렬하는 것이 좋아보이는 상황이 됐다!
그래서 sortedWith을 사용했다.
여러가지 조건을 추가해야했기 때문이다.
다이아몬드 개수 내림차순으로 정렬하는데 같으면 철 개수 내림차순으로 정렬하고, 같으면 돌 개수 내림차순으로 정렬하는 비교 조건을 넣었다.
이렇게 하고 나니까 이전에 엄청 길었던 when을 사용하지 않아도 됐고 그냥 차례대로 리스트를 순회하면서 다이아몬드 곡괭이가 다 떨어질때까지 다이아몬드 곡괭이를 쓰고 그 다음에 철 곡괭이 떨어질 때까지 철 곡괭이 쓰고 그 다음에 돌 곡괭이 떨어질 때까지 돌 곡괭이 쓰고 피로도 계산한 결과를 넘겨주기만 하면 됐다.
당연히 제출하니까 통과했다.
이 문제에서 가장 중요했던 포인트는 정렬이었던 거 같다.
사실 앞에서부터 쭉~ 가야한다는 문제 조건 때문에 생각지 못한 부분이었는데 사용할만큼만 리스트를 구성하면 정렬을 해도 상관없다는 게 나에게 놀라운 깨달음이었다.
해당 방법으로 작성한 코드는 다음과 같다.
class Solution {
private val table = arrayOf(arrayOf(1, 1, 1), arrayOf(5, 1, 1), arrayOf(25, 5, 1))
private val tier = hashMapOf("diamond" to 1, "iron" to 2, "stone" to 3)
fun solution(picks: IntArray, minerals: Array<String>): Int {
var answer = 0
val blockList = minerals.map { tier[it] }.chunked(5).let { list ->
list.subList(0, if (list.size > picks.sumOf { it }) picks.sumOf { it } else list.size).sortedWith(
compareBy({ dia -> -dia.count { it == 1 } }, { iron -> -iron.count { it == 2 } }, { stone -> -stone.count { it == 3 } })
)
}
blockList.forEach { block ->
if (picks[0] != 0) {
answer += calTiredness(block, 0)
picks[0]--
} else if (picks[1] != 0) {
answer += calTiredness(block, 1)
picks[1]--
} else {
answer += calTiredness(block, 2)
picks[2]--
}
}
return answer
}
private fun calTiredness(block: List<Int?>, num: Int): Int {
return block.sumOf { table[num][it?.minus(1)!!] }
}
}
'Kotlin > Algorithm Problems' 카테고리의 다른 글
<백준> 합분해(Gold 5) (0) | 2024.02.02 |
---|---|
<백준> 신기한 소수(Gold 5) (1) | 2024.01.31 |
<백준> 로봇 청소기(Gold 5) (1) | 2024.01.29 |
<프로그래머스> 거리두기 확인하기(Lv.2) (1) | 2024.01.26 |
<백준> 톱니바퀴(Gold 5) (1) | 2024.01.25 |