ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Exercism - Luhn(with.Kotlin)
    문제풀이/Exercism 2019. 8. 19. 14:34
    반응형

    [Instructions]

    Given a number determine whether or not it is valid per the Luhn formula.

    The Luhn algorithm is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers and Canadian Social Insurance Numbers.

    The task is to check if a given string is valid.

    Validating a Number

    Strings of length 1 or less are not valid. Spaces are allowed in the input, but they should be stripped before checking. All other non-digit characters are disallowed.

    Example 1: valid credit card number

    4539 1488 0343 6467

    The first step of the Luhn algorithm is to double every second digit, starting from the right. We will be doubling

    4_3_ 1_8_ 0_4_ 6_6_

    If doubling the number results in a number greater than 9 then subtract 9 from the product. The results of our doubling:

    8569 2478 0383 3437

    Then sum all of the digits:

    8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80

    If the sum is evenly divisible by 10, then the number is valid. This number is valid!

    Example 2: invalid credit card number

    8273 1232 7352 0569

    Double the second digits, starting from the right

    7253 2262 5312 0539

    Sum the digits

    7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57

    57 is not evenly divisible by 10, so this number is not valid.

     

    [Solution1]

    object Luhn {
        fun isValid(s: String): Boolean {
    
            val strReplaceSpace = s.replace(" ", "")
    
            if(strReplaceSpace.length < 2) return false
    
            val sum = strReplaceSpace
                    .mapIndexed { index, c ->
                        if(!c.isDigit())
                            return false
    
                        val num = c.toString().toInt()
    
                        if(checkDouble(index, strReplaceSpace.length)) {
                            val doubleNum = num * 2
    
                            if(doubleNum > 9){
                                return@mapIndexed doubleNum - 9
                            }
                                return@mapIndexed doubleNum
                        }
    
                        return@mapIndexed num
                    }
                    .toIntArray()
                    .sum()
    
            return sum % 10 == 0
        }
    
        private fun checkDouble(index:Int, strLength: Int): Boolean =
                if(strLength.isOdd())
                    index.isOdd()
                else
                    !index.isOdd()
    
        private fun Int.isOdd(): Boolean {
            return this % 2 != 0
        }
    
    }

    최초에 생각하는대로 규칙을 반견하여 작성함

    [Solution2]

    object Luhn {
        fun isValid(s: String): Boolean {
    
            val strReplaceSpace = s.replace(" ", "")
    
            if(strReplaceSpace.length < 2) return false
    
            val sum = strReplaceSpace
                    .mapIndexed { index, c ->
                        if(!c.isDigit())
                            return false
    
                        if(checkDouble(index, strReplaceSpace.length))
                            c.toString().toInt() * 2
                        else
                            c.toString().toInt()
                    }
                    .map {
                        if(it > 9)
                            it - 9
                        else
                            it
                    }
                    .sum()
    
            return sum % 10 == 0
        }
    
        private fun checkDouble(index:Int, strLength: Int): Boolean =
                if(strLength % 2 != 0)
                    index % 2 != 0
                else
                    index % 2 == 0
    
    }

    홀수짝수 여부를 구분하는 함수를 줄이고 처리함

    [Solution3]

    object Luhn {
        fun isValid(s: String): Boolean {
    
            val strReplaceSpace = s.replace(" ", "")
    
            if(strReplaceSpace.length < 2) return false
    
            val sum = strReplaceSpace
                    .reversed()
                    .mapIndexed { index, c ->
                        if(!c.isDigit())
                            return false
    
                        if(index % 2 != 0)
                            c.toString().toInt() * 2
                        else
                            c.toString().toInt()
                    }
                    .map {
                        if(it > 9)
                            it - 9
                        else
                            it
                    }
                    .sum()
    
            return sum % 10 == 0
        }
    
    }

    문자열 자체를 reversed() 하여 식을 간소화 시킴

    [Solution4]

    object Luhn {
        fun isValid(s: String): Boolean {
    
            val strReplaceSpace = s.replace(" ", "")
    
            if(strReplaceSpace.length < 2) return false
    
            if(strReplaceSpace.any { !it.isDigit() }) return false
    
            val sum = strReplaceSpace
                    .reversed()
                    .map {
                        it.toString().toInt()
                    }
                    .mapIndexed { index, i ->
                        if(index % 2 != 0)
                            i * 2
                        else
                            i
                    }
                    .sumBy {
                        if(it > 9)
                            it - 9
                        else
                            it
                    }
    
            return sum % 10 == 0
        }
    
    }

    isDigit 하는 부분을 map 외부로 빼냄

    정수로 변경하는부분을 사전 처리하도록 변경

    map 과 sum 을 합쳐서 sumby 로 처리함

    반응형

    댓글

Designed by Tistory.