오늘 푼 문제
https://school.programmers.co.kr/learn/courses/30/lessons/12931
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
코드
내 코드
import Foundation
func solution(_ n: Int) -> Int {
var answer: Int = 0
var num: Int = n
while num > 0 {
answer += num % 10
num /= 10
}
return answer
}
while 반복문 안에서, answer (자릿수의 합)을 계산하였다.
num % 10 으로, 일의 자릿수를 가져와서 더하고,
num /= 10 으로, 일의 자리 숫자를 지우는 과정을 하여 다음 반복에서 다음 자리수를 answer에 더하도록 하였다.
다른 사람의 코드
func solution(_ n : Int) -> Int {
var answer: Int = 0
for i in String(n) {
print(type(of: i)) // Character
answer += Int(String(i))!
}
return answer
}
n 을 먼저 String 으로 변환 후, for 반복문에서 각 자릿수에 character 타입으로 접근하도록 하였다.
answer 에 i 를 더할 때는, 다시 Int 형으로 변환해야 하는데,
character 를 바로 Int 로 바꾸기 위해서는 String 으로 중간에 바꾸는 과정이 필요하다.
이 때 강제 옵셔널 언래핑을 진행하였다.
(변환이 실패할 경우 런타임 오류가 발생할 수 있는데, 변환이 항상 성공할 것으로 예상했기에(i가 Character이고, 그것을 String 으로 변환한 값이 Int 로 변환이 가능하다.) 큰 문제가 안됨.)
Int(String(i))! 도 가능하지만, .wholeNumberValue 프로퍼티도 가능하다.
이번에는 강제 언래핑이 아닌, 더 안전한 방식인 if let 을 사용해보았다.
import Foundation
func solution(_ n:Int) -> Int {
var answer: Int = 0
for i in String(n) {
if let digit = i.wholeNumberValue {
answer += digit
}
}
return answer
}
각 문자가 실제로 숫자를 나타내는 경우에만 합계에 추가되며, 만약 문자가 숫자가 아닌 경우에는 무시된다.
이는 Swift 타입 안전성과 옵셔널 처리의 이점을 활용한 것이다.
이번에는, 이전에 배웠던 reduce 메소드를 사용해보자.
reduce 사용한 코드
import Foundation
func solution(_ n: Int) -> Int {
return String(n).reduce(0, { $0 + Int(String($1))! })
}
느낀점
문제를 풀 때 closure, reduce 처럼 함수형 프로그래밍의 이점을 제대로 사용하지는 못하는 것 같다.
똑같은 문제를 풀더라도, 다른 사람의 코드를 보면서 다양한 접근방식을 배우고 적용해보는 연습을 하는 것이 중요하다.
reduce 복습
reduce 메소드는 컬렉션에 있는 모든 요소를 하나의 값으로 결합하기 위해 사용된다. 이 메소드는 컬렉션의 요소를 순서대로 처리하면서, 각 요소에 대해 사용자가 제공한 결합 작업(Closure)을 수행한다.
즉, reduce는 컬렉션의 모든 요소를 축소(reduce) 하여 단일 값으로 만드는 것이다.
func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Self.Element) throws -> Result
) rethrows -> Result
Result 는 reduce 연산 결과의 타입이다. (제네릭)
initialResult 는 연산의 시작점에 사용되는 초기값!
nextPartialResult 는 Closure 로서, 누적된 결과 (Result) 와 현재 처리중인 요소(Element) 를 받아 다음 누적 결과를 반환한다.
예시 코드
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(0, { $0 + $1 })
print(sum) // 출력: 15
reduce의 첫 번째 인자로 0을 전달하여 누적 합계의 시작 값을 지정하고, 클로저에서는 두 인자의 합($0 + $1)을 계산하여 반환.
그럼 이제 해당 문제의 코드도 쉽게 이해가 될 것이다.
다시 코드를 보자.
import Foundation
func solution(_ n: Int) -> Int {
return String(n).reduce(0, { $0 + Int(String($1))! })
}
여기서는 String(n)으로 n을 문자열로 변환한 후, 이 문자열의 각 문자를 reduce 메소드를 사용해 순회하였다.
reduce의 첫 번째 인자로 0을 사용하여 합계에 사용할 초기값을 설정하였다.
클로저에서는 $0(누적된 합계 result) 와 $1(현재 문자 element)를 사용하였는데,
현재 문자를 먼저 String 으로 변환하고, 그 다음 Int 로 변환하였다. (Int(String($1)!)
이렇게 변환된 정수 값을 다시 $0 에 더한 것이다.