[프로그래머스] 둘만의 암호

neoneoneo·2024년 3월 21일
0

kotlin

목록 보기
41/49

문제

둘만의 암호

요약 | 알파벳 목록에서 특정 문자를 뺐을 때, 주어지는 문자열의 알파벳 위치에서 index 숫자만큼 밀어낸 암호문 결과를 출력하라.

나의 풀이 실패기

class Solution {
    fun solution(s: String, skip: String, index: Int): String {
        var answer: String = ""        
        s.forEach { it ->
            var skipCnt = 0
            skip.forEach { skipThis ->
                if (it.toInt() < skipThis.toInt() && skipThis.toInt() < it.toInt() + index) {
                    skipCnt++
                }
            }
            if (it.toInt() + index + skipCnt > 122) {
                answer += ((it.toInt() + index + skipCnt) - 26).toChar()
            } else {
                answer += (it.toInt() + index + skipCnt).toChar()
            }            
        }                
        return answer
    }
}

목표는
1. s의 char에 하나씩 접근(it)
2. it의 아스키값 ~ it아스키값+index값 사이에 skip의 아스키값이 몇 개 포함되는지 확인한다.
3. it의 아스키값 + index + 포함하고 있는 skip 개수를 한다.
3-1. 이때 %26하여 알파벳 범위를 벗어나면 다시 a부터 시작하도록 한다.
였으나.. 정상 작동 하지 못 하였다.
특히 "yyyy" 문자를 "za"를 스킵하고 2씩 인덱스가 넘어간 결과를 받고싶다고 했을 때, 제대로 처리를 못 하였다. 이런 케이스에서는 skipCnt를 특수하게 처리를 해주어야겠다 싶어서 수정을 해봤고,

class Solution {
    fun solution(s: String, skip: String, index: Int): String {
        var answer: String = ""        
        s.forEach { it ->
            var skipCnt = 0
            skip.forEach { skipThis ->
                if (it.toInt() + index > 122) {
                    var temp = 0
                    skip.forEach { i ->
                        if (it.toInt() < i.toInt() && i.toInt() <= 122) {
                            temp ++
                        }
                    }                    
                    skipCnt = 122 + temp - it.toInt()                   
                } else {
                    if (it.toInt() < skipThis.toInt() && skipThis.toInt() < it.toInt() + index) {
                        skipCnt++
                    }
                }              
            }
            if (it.toInt() + index + skipCnt > 122) {
                answer += ((it.toInt() + index + skipCnt) - 26).toChar()
            } else {
                answer += (it.toInt() + index + skipCnt).toChar()
            }            
        }                
        return answer
    }
}

이런 코드가 나왔으나,,, 막상 제출하면 모두 fail..!
문제를 너무 복잡하게 접근하고 있다는 생각이 들었고 처음부터 풀자고 생각했지만.. 당최 어떻게 풀어야할지 감이 오지 않아 이번에는 로직 서치를 하여 도움을 받았다.

고수의 풀이

class Solution {
    fun solution(s: String, skip: String, index: Int): String {
        var answer: String = ""        
        val alphabets = ('a'..'z').filter { !skip.contains(it) }.sorted()
        val alphaLength = alphabets.size      
        s.forEach {
            answer += alphabets[(alphabets.indexOf(it) + index) % alphaLength]
        }     
        return answer
    }
}
  • alphabets = ('a'..'z').filter { !skip.contains(it) }.sorted() : 알파벳 a~z 중에 filter하여 skip에 포함하고 있는 문자는 제외하고 저장한다. 이때 오름차순으로 정렬하여 정제된 알파벳 목록을 저장한다.
  • alphaLength = alphabets.size : index를 더했을 때에 z를 넘어가는 경우에 대비하기 위해 정제된 알파벳 목록의 길이 값을 기억해둔다.
  • forEach문으로 각 문자를 돌면서,
    • (alphabets.indexOf(it) + index) % alphaLength : 해당 문자가 정제된 알파벳 리스트에서 몇 번째에 있는지 확인하고 그 값에 index를 더한다. z를 넘어갈 수 있으므로 정제된 알파벳 리스트 길이로 나누고 나머지 값을 취한다. 이게 바로 암호문 결과의 인덱스 값이 된다.
    • answer += alphabets[...] 위에서 취한 인덱스 값을 정제된 알파벳 리스트에서 찾아 결과에 적립한다.

배운점 & 느낀점

  • 역시 고수들은 filter을 적재적소에 사용한다.
  • 다른 고수들의 풀이도 함께 보니 이번 문제는 내가 접근한 방식으로도 풀 수 있는 문제인 것 같다. 다만 식을 세우는 데에 있어서 너무 복잡하게 복잡하게 파고들어가 길을 잃었고 문제를 풀어낼 의지를 상실해버린 게 패인이라면 패인이다. 그렇지만 덕분에 고수의 풀이를 여럿 볼 수 있었고 이번 글에서 소개한 풀이처럼 접근을 새롭게하여 아주 간단하게 문제를 풀어내어 버리는 사례를 공부 할 수 있었으니까, 라고 스스로를 위로해본다. 🥹

[TIL-240321]

0개의 댓글