[Swift/프로그래머스] 홀짝에 따라 다른 값 반환하기

sonny·2024년 11월 23일
2

TIL

목록 보기
50/133

나의 답)

import Foundation

func solution(_ n:Int) -> Int {
 return  n % 2 == 1 
    ? (1...n).filter { $0 % 2 == 1}.reduce(0, +)
    : stride(from: 0, through: n, by: 2).map { $0 * $0 }.reduce(0, +)
}

풀기까지의 과정

문제에서 "홀수라면 n 이하의 홀수의 합", "짝수라면 n 이하의 짝수의 제곱의 합"이라는 두 가지 조건이 주어졌는데,

이걸 어떻게 효율적으로 나눠서 처리할지 고민했다.

처음에는 조건별로 따로따로 구현하려다 보니 코드가 완전 장황해져서 유지보수가 어려워질 것 같다는 생각이 들다가

얼마 전에 코테를 풀며 알게된 메서드를 이용해보면 될 것 같다는 생각이 들었다.

조건에 맞는 값을 필터링하면서도 반복문을 효율적으로 작성하고 싶었지만,

처음에는 stride 메서드의 존재를 잊고 있었고.. for문으로 처리하려 했었다.

1차 코드 [ for문의 활용 ]

func solution(_ n: Int) -> Int {
    var sum = 0
    for i in 1...n {
        if n % 2 == 1 { // 홀수 조건
            if i % 2 == 1 { // i도 홀수인 경우만 합산
                sum += i
            }
        } else { // 짝수 조건
            if i % 2 == 0 { // i가 짝수인 경우만 제곱하여 합산
                sum += i * i
            }
        }
    }
    return sum
}

이건 내 기준 코드가 길어지고 가독성이 떨어지게 만들었다...

짝수 조건과 홀수 조건을 for i in 1...n 반복문 안에서 모두 처리하려 하다 보니, 매번 조건을 확인해야 했고

짝수일 때 짝수만 처리하면 되는 문제를 불필요하게 i값마다 조건을 검사하게 만들었다.

if 문 안에 또 다른 if 문이 중첩되면서 코드가 읽기 어려워지기도 했고,

특히 if i % 2 == 1과 같은 조건들이 여러 번 반복되면서 실수하기 쉬운 구조가 된 것 같았다.

예를 들어 n1이거나 2인 경우에도 for 반복문이 실행되어야 하는데,

결과값이 잘못 나오는 경우가 있었다.

n = 1일 때, i % 2 == 1 조건은 만족했지만 다른 경계값에서는 놓칠 가능성이 있었고 결국 ..

n = 2일 때 짝수 조건에서 i % 2 == 0가 제대로 동작하지 않았다...
.
.
.
.

2차 코드 [ stride의 활용 ]

func solution(_ n: Int) -> Int {
    if n % 2 == 1 { // n이 홀수인 경우
        return stride(from: 1, through: n, by: 2).reduce(0, +)
    } else { // n이 짝수인 경우
        return stride(from: 2, through: n, by: 2).map { $0 * $0 }.reduce(0, +)
    }
}

if-else 구문을 사용해 stride로 간단하게 두 가지 조건을 처리할 수 있었다.

특히, "짝수냐, 홀수냐"라는 조건을 나누는 데서 n % 2 == 0 표현이 얼마나 직관적인지 새삼 깨닫는 순간이었다

복잡하게 생각할 필요 없이, 조건을 깔끔하게 처리하는 것이 중요하다는 생각도 하고..

아무튼 그래서 stride(from:to:by:)stride(from:through:by:)를 활용하면 반복문에서 특정 범위의 값들을 간결하게 필터링할 수 있다는 것을 알고 있었으니,

이를 통해 짝수와 홀수를 빠르게 구분하고, 불필요한 조건문을 줄일 수 있었다.

처음에는 문제를 한꺼번에 처리하려고 했지만,

"홀수 합""짝수 제곱의 합"을 별도로 나눠서 생각하니 훨씬 접근이 좀 쉬워졌던 것 같다.

공책에 적으며 문제를 작은 단계로 나누고 각 부분을 해결한 뒤 합치는 방식을 글로 써본 것이 도움이 많이 됐다.
.
.
.
.

최종 코드 [ 삼항연산자 활용 ]

import Foundation

func solution(_ n:Int) -> Int {
 return  n % 2 == 1 
    // 삼항 연산자 이용
    ? (1...n).filter { $0 % 2 == 1}.reduce(0, +)
    : stride(from: 0, through: n, by: 2).map { $0 * $0 }.reduce(0, +)
}

사실 2차코드에서 마무리하려했는데,

문제 자체가 1 아니면 2 이런식으로 둘 중 하나의 형태로 되어있으니 삼항연산자를 이용해보고 싶다는 생각이 들었다.

결론적으로 filter 함수가 더 추가되긴 했지만,

삼항 연산자를 활용해 코드의 길이를 줄이면서도 조건을 좀더 명확하게 구분할 수 있었다고 느꼈다.

filter를 사용해 원하는 조건의 값만 걸러낼 수 있어 불필요한 반복문을 제거할 수 있고,

stride로 짝수만 쉽게 생성해주면 가독성과 효율성을 동시에 높여주는 것 같다는 생각이 들었다.

그리고 reduce를 통해 합계를 간결하게 구할 수 있었다.

삼항 연산자를 활용해 조건별 로직이 잘 드러날 수 있게 고차 함수와 적절히 조합해본 도전이었다.


음 ...

이런 방식으로 문제를 작게 나눠 간결하게 만든 뒤 해결하는 방법과

Swift 고차 함수의 활용성이 정말 무궁무진하다라고 생각하며 푼 것 같다.

앞으로도 다양한 문제를 효율적으로 플고 싶은 욕심이 생기기도 했고,,

가독성 높은 코드를 작성하는 데 주력해야겠다고 다짐도 해보는 시간이었달까

profile
iOS 좋아. swift 좋아.

3개의 댓글

comment-user-thumbnail
2024년 11월 23일

와 50번째 틸,,,
진짜 살면서 처음 하는 작업을
이렇게 바로 유지할 수 잇다니 멋져요

1개의 답글

관련 채용 정보