본문 바로가기

Algorithm

[Algorithm - Method Chaining ] Kotlin - programmers Lv1 [ 신규아이디 추천 ]

[ Algorithm Link ]

 

프로그래머스

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

programmers.co.kr

 


 

최종 코드 미리보기

 

fun solution(new_id: String): String {
    return new_id.step1().step2().step3().step4().step5().step6().step7()
}

fun String.step1 () = this.lowercase()

fun String.step2 () = this.filter {
    listOf<Char>('.', '-', '_').contains(it) || ('a'..'z').contains(it) || ('0'..'9').contains(
        it
    )
}

fun String.step3 () : String {
    tailrec fun test(str: String): String {
        if (!str.contains("..")) return str
        return test(str.replace("..","."))
    }

    return test(this)
}

fun String.step4 () = this.removePrefix(".").removeSuffix(".")

fun String.step5 () = this.ifEmpty { "a" }

fun String.step6 () = (if (this.length > 15) this.take(15) else this).removeSuffix(".")

fun String.step7 () : String {
    tailrec fun minLength (str: String) : String {
        if (str.length > 2) return str
        return minLength(str + str.last())
    }

    return minLength(this)
}

 

[ 리팩토링 ]

  • solution 의 각 step 들을 함수로 분리.
  • 불 필요한 변수 할당을 피하고 가독성 향상을 위해 while 문을 tailrec 함수로 리팩토링.
  • 일부 반복문을 kotlin 표준 라이브러리 함수로 리팩토링.

 

🟥 trimStart(), trimEnd() vs removePrefix(), removeSuffix() 비교

  • trimStart(){ }, trimEnd(){ } → 불특정 다수의 문자열 조건으로 제거할 수 있다 ex) trimStart() { 조건 }
  • removePrefix(), removeSuffix() → 특정 하나의 문자만 제거할 수 있다.

 

 

 

 

 

제출 코드 - 통과 → 리팩토링 전

 

fun solution(new_id: String): String {
    var answer: String = ""

    var step1 = new_id.lowercase()

    var step2 = step1.filter {
        listOf<Char>('.', '-', '_').contains(it) || ('a'..'z').contains(it) || ('0'..'9').contains(
            it
        )
    }

    var step3 = step2

    while (step3.contains("..")) {
        step3 = step3.replace("..", ".")
    }


    var step4 = step3

    while (step4.first() == '.') {
        step4 = step4.drop(1)

        if (step4.isEmpty()) {
            break
        }
    }

    if (step4.isNotEmpty()) {
        while (step4.last() == '.') {
            step4 = step4.dropLast(1)

            if (step4.isEmpty()) {
                break
            }
        }
    }

    var step5 = step4.ifEmpty { "a" }

    var step6 = (if (step5.length > 15) step5.take(15) else step5)
    if (step6.last() == '.') {
        step6 = step6.dropLast(1)
    }

    var step7 = step6
    while (step7.length < 3) {
        step7 += step7.last()
    }

    answer = step7

    return answer
}

 

[ 작성코드 리뷰 ]

  • 문제에서부터 solution 함수가 return 까지의 프로세스를 단계로 나누어서 알려주어서 이 일고리즘은 단계를 나누어서 작성하면 좋을 것 같다는 생각으로 step을 나누어서 작성했는데, 단계를 나누어서 작성은 했으나 코드 분리를 흉내만 낸 코드만 되었다 이유는 아래와 같다.
    • 1️⃣ 재사용성 X - 특정 step을 재사용할 수 없다.
    • 2️⃣ 각 단계 독립성 X - 특정 step이 빠질 경우 나머지 step의 변수도 새로 할당 해주어야 하는 번거로움이 있다.
    • 3️⃣ 가독성 ↓ - 불필요한 변수할당, 조건문 단순화 필요

 

🏗️ 리팩토링 방향 → 함수 분리 후 메서드 체이닝, 각 step 함수와 반복문 단순화 

 

 

 

알고리즘 회고

 

다른 사람들의 코드를 많이 보는 것의 중요성

  • 다른 사람들의 풀이 방식을 접하면서 좋은 부분은 학습하고, 비교해가면서 여러 방식들을 학습 해보도록 해야겠다.

 

 

 

 

 

 


[Reference]