[프로그래머스] 대충 만든 자판

neoneoneo·2024년 3월 20일
0

kotlin

목록 보기
40/49

문제

대충 만든 자판

요약 | 여러 개의 키 값이 할당된 자판이 있다. 목표로 하는 문자열을 작성할 수 있는 최소한의 자판 눌림 횟수를 구하라.

나의 풀이

class Solution {
    fun solution(keymap: Array<String>, targets: Array<String>): IntArray {
        var answer: IntArray = intArrayOf()              
        for (i in 0 until targets.size) {
            var pushCount = 0
            for (j in 0 until targets[i].length) {
                var compareCount: MutableList<Int> = mutableListOf()
                for (k in 0 until keymap.size) {
                    if (keymap[k].contains(targets[i][j])) {                  
                        compareCount.add(keymap[k].indexOf(targets[i][j]))
                    }
                }
                if (compareCount.size >= 1) {
                    pushCount += compareCount.minOrNull()!! + 1
                    compareCount.clear()
                } else {
                    pushCount = -1
                    break
                }
            }
            answer += pushCount
        }              
        return answer
    }
}

삼중 for문을 사용한 로직이다.
1. targets를 하나씩 불러온다(첫 번째 for문)
2. targets에 들어있는 문자를 하나씩 불러온다(두 번째 for문)
3. keymap을 하나씩 불러온다(세 번째 for문)
4. 불러온 keymap에 확인할 문자가 포함되어 있는지 확인한다.
4-1. 해당 문자가 keymap의 몇 번째 인덱스가 있는지 저장해둔다.
5. 포함하고 있는 keymap들의 인덱스 값중 가장 작은 값을 push 횟수에 저장해둔다.
5-1. 만약 포함하고 있는 keymap이 없으면 -1을 push 횟수에 저장해둔다.
6. 위 과정을 targets에 대해 반복하면 최종적으로 리턴할 값에 합쳐진 push 횟수를 저장하고 push 횟수는 0으로 초기화하여 다음 targets 문자에 대한 처리를 반복한다.

고수의 풀이

class Solution {
    fun solution(keymap: Array<String>, targets: Array<String>): IntArray =
        targets.map { str ->
            str.map { c -> keymap.map { it.indexOf(c) + 1 }
                .filterNot { it < 1 }
                .let { list ->
                    if (list.isEmpty()) -1
                    else list.minOf { it }
                }
            }.let { if ( it.contains(-1)) -1 else it.sum() }
        }.toIntArray()
}

이 코드는 targets 배열에 있는 각 문자열을 keymap에서 찾아 해당 위치의 합계를 계산하고, 만약 유효하지 않은 위치가 있다면 -1을 반환한다.

  • targets.map { str -> ... } : targets에 들어있는 각 문자열(str)에 대해
  • str.map { c -> ...} : 각 문자열에 대한 문자(c)에 접근하는데
  • keymap.map { it.indexOf(c) + 1 } : keymap 배열에 있는 각 문자열에 대해, 문자열 안에 c 문자의 인덱스를 찾아 1을 더한 값을 반환할 건데
  • .filterNot { it < 1 } : 인덱스가 1보다 작은 것을 필터링하고(위치를 1씩 증가시켜서 반환했기 때문에 1보다 작은 값은 유효하지 않음),
  • .let { list -> ... } : 필터링된 유효한 위치 목록(list)에 대해
  • if (list.isEmpty()) - 1 else list.minOf { it } : 유효한 위치 목록이 비어있으면 -1을 반환하고, 그렇지 않으면 목록에서 최소값을 반환한다.
  • .let { if ( it.contains(-1)) -1 else it.sum() } : 각 문자열에 대한 위치 합계를 구하는데, 만약 -1이 포함되어 있으면 -1을 반환한다.
  • .toIntArray() : 최종 결과를 정수 배열로 변환하여 반환한다.

배운점 & 느낀점

  • 역시 고수님들은 map, let, filter 같은 함수를 잘 쓴다. 처음 문제를 봤을 때 map으로 풀 수 있지 않으려나 했는데, 시도를 못 했다. 이 코드를 여러번 써보고 다른 사례를 좀 찾아보면서 map의 쓰임새에 대해 공부를 더 해봐야겠다.
  • 이번 문제는 시간은 좀 걸렸지만, 내 머리로만 모든 로직을 짜서 풀 수 있었다. 조금 더 간결하게 코드를 작성해서 가독성 있게 작성할 수 있으면 좋을텐데, 아직은 연습이 더 필요한 것 같다.

[TIL-240320]

0개의 댓글