문제- 신규 아이디 추천
오랜만에 알고리즘 문제를 풀어봤는데 지금까지 Python으로 많이 풀어왔지만 이번엔 코틀린으로 한 번 풀어봤다.
생각보다 쉽지 않았고 시간이 많이 걸렸다.
람다로 짜는걸 좋아해서 람다로 풀어보기로 했다.
1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
it.toLowerCase().toString() // A -> a
첫 번쨰는 그렇게 어렵지 않다. map으로 1대1로 소문자로 바꿔준다.
2단계 newid에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거합니다.
.filter{it.isLetterOrDigit() || it.toString() == "-" || it.toString() == "_" || it.toString() == "."}
// "...!@bat#*..y.abcdefghijklm" -> [,.,.,.,b,a,t,.,.,y,.,a,b,c,d,e,f,g,h,i,j,k,l,m]
문자와 숫자인지 확인하고 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)만 fiter해서 리스트로 받아온다. 첫 번째와 두 번쨰 순서상 결과는 똑같기 때문에 1단계에 앞서 진행해줬다.
map으로 1대1로 반환했기 때문에 다시 리스트로 만들고 스트링으로 만들어야했다. 그래서 내가 생각난건 flatMap으로 일단 시도해보기로 했다.
.flatMap{it.toList()} // 다시 리스트로 만들어준다. "a","b","c" -> ["a",b","c]
.let{it.joinToString("")} // 리스트 요소들을 합쳐준다. ["a","b","c"] ->"abc"
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
.let{it.replace("\\.{2,}".toRegex(),".")}
// ... -> .
이 경우에는 Regex를 사용하면 간단하게 할 수 있었다. 앱 개발 할때도 Regex도 알고있으면 코드 수가 많이 줄 것 같다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
.removePrefix(".") .removeSuffix(".")
접두사,접미사에 특정 문자가 있으면 제거하는 아주 좋은 함수가 있었다!
5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.
.let{ if(it.isEmpty())"a"else it}
코드 그대로 빈 문자("")인지 확인하고 비었다면 a를 반환해주고 빈 문자가 아니라면 그대로 반환해준다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
.let{
if(it.length >= 16){
it.toString().removeRange(15,it.length).toString().removePrefix(".").removeSuffix(".")
}else it}
16자 이상인 체크하고 removeRange로 범위를 설정해서 index i5부터 끝가지 버려준다.
문제 그대로 .이 있는지 다시 확인해서 앞,뒤 지워준다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
.let{
if(it.length <= 2){
when(it.length){
1 -> "${it.get(0)}${it.last()}${it.last()}"
else -> "${it}${it.last()}"
}
}else it
}
여기서 어떻게 할까 많이 고민했지만 경우의 수가 2개(문자열이 1개 or 2개)라서 하드코딩하기로 했다.
class Solution {
fun solution(new_id: String): String = new_id
.filter{it.isLetterOrDigit() || it.toString() == "-" || it.toString() == "_" || it.toString() == "."}
.map{it.toLowerCase().toString()}
.flatMap{it.toList()}
.let{it.joinToString("")}
.let{it.replace("\\.{2,}".toRegex(),".")}
.removePrefix(".")
.removeSuffix(".")
.let{
if(it.isEmpty()){
"a"
}else it
}
.let{
if(it.length >= 16){
it.toString().removeRange(15,it.length).toString().removePrefix(".").removeSuffix(".")
}else it
}
.let{
if(it.length <= 2){
when(it.length){
1 -> "${it.get(0)}${it.last()}${it.last()}"
else -> "${it}${it.last()}"
}
}else it
}
}
1단계가 예전보다 많이 어려워졌다.. 카카오 문제라서 그런가
코틀린으로 푸니까 아주 신선했다.