본문 바로가기
알고리즘

[kotlin] 프로그래머스 - 주사위게임3 ; 코틀린 문법 연습

by 측면삼각근 2023. 8. 12.
728x90
반응형

최근들어 코틀린을 공부하고 있습니다.
하지만 코드 작성 경험이 적어 익숙해지기 위해 프로그래머스 기초 역량 트레이닝을 풀다, 문법적으로 공부하기 좋았던 문제를 정리합니다.

https://school.programmers.co.kr/learn/courses/30/lessons/181916

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


문제 설명

1부터 6까지 숫자가 적힌 주사위가 네 개 있습니다. 네 주사위를 굴렸을 때 나온 숫자에 따라 다음과 같은 점수를 얻습니다.

  • 네 주사위에서 나온 숫자가 모두 p로 같다면 1111 × p점을 얻습니다.
  • 세 주사위에서 나온 숫자가 p로 같고 나머지 다른 주사위에서 나온 숫자가 q(p ≠ q)라면 (10 × p + q)2 점을 얻습니다.
  • 주사위가 두 개씩 같은 값이 나오고, 나온 숫자를 각각 p, q(p ≠ q)라고 한다면 (p + q) × |p - q|점을 얻습니다.
  • 어느 두 주사위에서 나온 숫자가 p로 같고 나머지 두 주사위에서 나온 숫자가 각각 p와 다른 q, r(q ≠ r)이라면 q × r점을 얻습니다.
  • 네 주사위에 적힌 숫자가 모두 다르다면 나온 숫자 중 가장 작은 숫자 만큼의 점수를 얻습니다.

네 주사위를 굴렸을 때 나온 숫자가 정수 매개변수 a, b, c, d로 주어질 때, 얻는 점수를 return 하는 solution 함수를 작성해 주세요.

※ a, b, c, d는 1 이상 6 이하의 정수입니다.


입출력 예시

a b c d result
2 2 2 2 2222
4 1 4 4 1681
6 3 3 6 27
2 5 2 6 30

풀이

풀이는 모두 동일합니다.

주사위가 어떤 눈금이 몇개가 들어오는지가 중요한 문제이기에, HashMap을 이용하여 <주사위 눈금, 갯수>로 카운팅을 합니다.

이후 케이스에 따라 분기합니다.

최초 풀이

fun solution(a: Int, b: Int, c: Int, d: Int): Int {
        val map: HashMap<Int, Int> = HashMap<Int, Int>();
        map[a] = map.getOrDefault(a, 0) + 1
        map[b] = map.getOrDefault(b, 0) + 1
        map[c] = map.getOrDefault(c, 0) + 1
        map[d] = map.getOrDefault(d, 0) + 1
        return when(map.keys.size){
            1 -> 1111 * map.keys.first()
            2 -> {
                if (map.values.contains(3)) {
                    val p = map.filter { it.value == 3 }.keys.first()
                    val q = map.filter { it.value == 1 }.keys.first()
                    (10 * p + q) * (10 * p + q)
                } else {
                    val p = map.filter { it.value == 2 }.keys.first()
                    val q = map.filter { it.value == 2 }.keys.last()
                    (p + q) * abs(p - q)
                }
            }
            3 -> {
                val sameKeys = map.filter { it.value == 1 }.keys
                sameKeys.first() * sameKeys.last()
            }
            else -> map.keys.min()
        }
    }
  • getOrDefault로 값 또는 0을 가져와, 해당 눈금에 +1값을 할당해 주었습니다.
  • when문을 이용하여 케이스를 나누었습니다.
  • IDE환경에서는 min() 메서드가 동작하였으나, 프로그래머스 환경에서는 정상동작하지 않았습니다

프로그래머스 코틀린 컴파일러 버전은 1.6.10 인데 (로컬은 1.9.0 사용) 1.5버전부터 에러가 난다고 합니다.

풀이 문법 개선

fun solution(vararg ints: Int): Int {
        val map = ints.groupBy { it }.mapValues { it.value.size }
        return when (map.keys.size) {
            1 -> 1111 * map.keys.first()
            2 -> {
                if (map.values.contains(3)) {
                    // 3개가 같은 경우
                    val p = map.filter { it.value == 3 }.keys.first()
                    val q = map.filter { it.value == 1 }.keys.first()
                    (10 * p + q) * (10 * p + q)
                } else {
                    // 2개가 같은 경우
                    val p = map.keys.first()
                    val q = map.keys.last()
                    (p + q) * Math.abs(p - q)
                }
            }
            3 -> {
                // 2개 주사위만 같고, 나머지는 모두 다른경우, 나머지 2개 주사위의 곱
                val sameKeys: Set<Int> = map.filter { it.value == 1 }.keys
                sameKeys.first() * sameKeys.last()
                map.keys.min()
            }
            else -> map.keys.minOrNull() ?: 0
        }
    }

1. 인자를 하나하나 hashMap에 등록하는 것이 아니라, vararg로 받아, 함수 내부에서 Array로 사용할 수 있도록 받은 후 groupBy function으로 한번에 map에 등록하도록 하였습니다.

group by는 아래 형태로 사용할 수 있습니다.

inline fun <T, K> Sequence<T>.groupBy(
    keySelector: (T) -> K
): Map<K, List<T>>

예시

val words = listOf("a", "abc", "ab", "def", "abcd")
val byLength = words.groupBy { it.length }

println(byLength.keys) // [1, 3, 2, 4]
println(byLength.values) // [[a], [abc, def], [ab], [abcd]]

val mutableByLength: MutableMap<Int, MutableList<String>> = words.groupByTo(mutableMapOf()) { it.length }
// same content as in byLength map, but the map is mutable
println("mutableByLength == byLength is ${mutableByLength == byLength}") // true

2. min()에서 발생하는 컴파일 에러

minOrNull을 사용하여, null반환 처리를 한번 더 사용하였습니다.

반응형