ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 짝수와 홀수, 배열의 평균값, 자리수 합치기
    iOS 앱 개발 부트캠프/TIL 2024. 11. 3. 14:19

    짝수와 홀수

    문제 설명

    • 정수 num이 짝수일 경우 "Even"을 반환하고 홀수인 경우 "Odd"를 반환하는 함수, solution을 완성해주세요.

    제한 조건

    • num은 int 범위의 정수입니다.
    • 0은 짝수입니다.

     

    문제풀이

    다음과 같이 num % 2 == 0 을 조건으로 짝수 홀수를 나누려고 했는데, 15번의 테스트 중 한 번 에러가 났다.

    음수나 0 때문인가 생각도 해봤지만 0은 짝수로 처리되니 문제가 없고, 2로 나눠서 나머지가 0인지 보는 것이니 음수인 것도 문제가 없다.

    혹시나해서 음수나 0, 여러 짝수와 홀수, 큰 수도 입력하며 테스트 해봤는데 문제를 발견하질 못했다.

    어떤 테스트 값이 입력 되었길래 런타임 에러가 난 건지 모르겠다. 매개변수 타입이 Int이니 실수나 문자열이나 Int 범위를 넘는 숫자가 들어온 것도 아닐텐데.. 무슨 에러인지 좀 더 고민해봐야 할 것 같다.

    여하튼 문제를 풀기 위해 코드를 바꿔서 시도해보았다.

    func solution(_ num:Int) -> String {
        if num % 2 == 1 || num % 2 == -1 {
        	return "Odd"
        } else { 
        	return "Even" 
        }
    }

    나머지가 1인지를 판별하는 경우인데 이 경우 입력 값이 음수 일땐 나머지도 음수가 되므로 -1의 경우도 생각해서 조건문을 설정하였다.

    첫번째 방식과 다를 바 없다고 생각하지만 에러가 발생하지 않고 잘 해결되었다.

    그런데 처음의 코드보다 조건문이 길어진 부분이 있어 더 나은 방법이 없을까 하다가, 짝수 or 홀수의 단순한 조건이기 떄문에 삼항 연산자를 쓰면 더 간단해지겠다는 생각이 들었다.

    func solution(_ num:Int) -> String {
        num % 2 == 0 ? "Even" : "Odd"
    }

    삼항연산자를 쓰니 코드가 훨씬 간결해졌다.

    이것도 처음의 방식에서 if-else 대신 삼항연산자를 쓴 것뿐인데 잘 작동하는게 이상하다고 생각된다. if-else문과 삼항연산자의 다른 점이 뭔가 있는지 찾아봐야할 것 같다.

    그리고 짝수와 홀수, 음수와 양수 같은 참/거짓 정도의 단순한 조건문이 필요한 경우 삼항연산자가 더 나을 수 있을 것 같다.


    배열의 평균값

    문제 설명

    • 정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.

     

    문제 풀이

    반복문을 썼다면 다음과 같은 방식으로 구현해야 했겠지만,

    func solution(_ arr:[Int]) -> Double {
        var total = 0
        for number in arr {
            total += number
        }
        return Double(total) / Double(arr.count)
    }

    어제 공부한 고차함수의 reduce를 한 번 사용해보았다.

    func solution(_ arr:[Int]) -> Double {
        return Double(arr.reduce(0, +)) / Double(arr.count)
    }

    배열의 모든 수를 더하는 구문을 훨씬 간결하게 작성할 수 있다. 그리고 어제의 경험으로 형변환도 주의해서 작성하였다. for문을 사용하는 것보다 간단한 코드로 배열의 평균 값을 구할 수 있었다.


    자리수 더하기

    문제 설명

    • 자연수 N이 주어지면, N의 각 자릿수의 합을 구해서 return 하는 solution 함수를 만들어 주세요.
    • 예를들어 N = 123이면 1 + 2 + 3 = 6을 return 하면 됩니다.

     

    문제 풀이

    이 경우 숫자를 문자열로 변환한 뒤, character로 한 글자씩 저장해 다시 Int로 변환해 더한다면 풀 수 있을 것 같았다.

    func solution(_ n:Int) -> Int
    {
        var charNumber: [Character] = [] // 문자열로 변환한 숫자를 한 글자씩 저장하기 위한 배열
        var stringNumbers = String(n) // 정수 입력 n을 문자열로 변환
        var sum = 0 // 반환할 결과를 저장할 변수
        
        // 한 글자씩 char 배열에 추가하기
        for char in stringNumbers {
            charNumber.append(char)
        }
        // character가 저장된 배열 하나씩 가져와 더하기
        for i in charNumber {
            if let num = Int(String(i)) { // 옵셔널 처리하기
                sum += num
            }
        }
      
        return sum
    }

    단순하게 형변환을 하려고 했더니 character는 Int로 형변환이 안되어서 String으로 먼저 형변환을 한 뒤 다시 Int로 형변환 하는 식으로 해야했다.

    그리고 문자는 공백이 있거나 알파벳 같은 숫자로 변환할 수 없는 문자가 포함되어 있을 수 있기 때문에 Int(String(i))의 반환 값이 옵셔널 값이어서 옵셔널 처리를 해야했다.

    입력으로 받는 매개변수가 Int 타입이고 이걸 형변환 한 것이기 때문에 이상한 값이 들어가진 않을 것이라 sum += Int(String(i))! 같이 강제 언래핑을 해도 되겠지만, 안전한 옵셔널 처리 습관을 들이기 위해 if let 구문을 사용해 옵셔널 바인딩 처리를 하는 방법을 선택했다.

     

    더 나은 방법 생각하기

    작성한 코드를 다시 읽어보면서 생각을 다시 해보았는데, charNumber 배열을 쓴 것은, 문자열에서 문자를 하나씩 배열에 저장한 뒤에 그 배열을 다시 반복문에서 사용해야 글자를 하나씩 읽어 올 수 있을 것이라고 생각해서였다.

    그런데 애초에 charNumber 배열에 한 글자씩 문자를 저장할 때, 문자열로 변환 된 stringNumbers에서 한 글자씩 charNumber에 저장할 수 있었다. 이것이 가능하다면 character 타입의 문자를 저장하겠다고 배열을 만들어 한 글자씩 저장할 필요가 없다. 처음부터 문자열로 변환된 숫자를 하나의 반복문에서 한 글자씩 뽑아내면 되는 것이었다.

    또한 stringNumbers 변수도, 반복문을 작성할 때 형변환을 하면 딱히 선언할 필요 없는 변수인 것이다.

    func solution(_ n:Int) -> Int
    {
        var sum = 0
        
        for char in String(n){ // 반복문 작성할 때 형변환 하기
            if let num = Int(String(char)){ // 옵셔널 바인딩 하기
                sum += num
            }
        }
        
        return sum
    }

    이렇게 하면 훨씬 간결한 코드로 자릿수 더하기 코드를 완성할 수 있다.

    코드가 단순해져서인지 실행 시간도 0.05ms ~ 0.1ms에서 0.03ms ~ 0.05ms로 절반으로 줄어들었다.

Designed by Tistory.