import Foundation
func solution(_ n:Int) -> Int {
let num = n
var a = 1
var lst : [Int] = []
while a <= Int(sqrt(Double(n))) {
if n % a == 0 {
lst.append(a)
lst.append(n/a)
}
a += 1
}
let setlst = Set(lst)
return setlst.reduce(0,+)
}
풀면서 공부한 부분
리스트 선언 후 초기화 안익숙한데 저런식으로 써야 하는 것
python에서 제곱 곱하는 연산자 (**) 가 안먹어서 알아보니 foundation 라이브러리에 정의되어 있는 sqrt() 를 사용해야 함.
- 제곱을 구하고 싶다면 pow(), 제곱근은 sqrt()
- 둘 다 인자로 Double, Float를 받기 때문에 Int를 넣고 싶다면 자료형 변환이 필요함. 대소비교를 위해 다시 Int로 받고 싶다면 Int로 한번 더 감싸줘야 함.
Array 를 Set으로 바꾸기 위해서는 저런식으로 선언을 해 줘야 함. Set이 대문자임을 주의.
Swift 에는 list 대신 Array 가 있는데, 이것도 아직 익숙치가 않아서 변수명을 저런식으로 썼다... 앞으로 arr 라고 쓰는 습관을 들여야겠음.
다른 사람의 풀이를 확인해보니 너무 고수느낌이 나서, 일단 챗지피티한테 Swift가 권장하는 방식으로 효율적인 코드를 다시 짜 달라고 했더니 받은 코드.
import Foundation
func solution(_ n: Int) -> Int {
// n이 1 이하인 경우, n 자체를 반환하고 함수 실행을 종료
guard n > 1 else {
return n
}
var divisors = Set<Int>()
for divisor in 1...Int(sqrt(Double(n))) {
if n % divisor == 0 {
divisors.insert(divisor)
divisors.insert(n / divisor)
}
}
return divisors.reduce(0, +)
}
개선된 점
n 이 0인 경우, 0을 반환하도록 guard 문을 써줌. guard 문은 제시된 조건이 아니라면 else 후의 코드를 실행하도록 설계된 조건문이다.
아예 약수 받는 리스트를 Set으로 선언함. Set은 사실 안 썼을때 정수 제곱근이 들어가는 것 같아서 추후에 추가한 코드였는데, 애초에 선언을 저렇게 하는게 당연히 더 좋겠군.
Set 에 값 집어넣기는 insert()
while문을 for_in 문으로 반복의 범위가 더욱 명시적으로 보인다. 지피티 말로는 while문보다 for in 문을 쓰는것이 오류가능성이 좋고 명시적이라 더 좋다고 하더라.
이제 이 풀이를 획기적으로 줄인 풀이.
func solution(_ n:Int) -> Int {
guard n != 0 else {
return 0
}
return Array(1...n).filter{n % $0 == 0}.reduce(0, +)
}
python 에서도 리스트 컴프리헨션 공부하면서 익숙해질 때 짜릿함이 있었는데, 이것도 노력해 봐야겠다.
라는 생각을 했는데...?!
근데 쓰다보니까 위 코드는 그냥 코드 길이를 짧게 하기 위해서 저렇게 쓴거고, n을 제곱근까지만 나누는게 더 효율적인거 아냐? 하는 생각이 들어서 두 방법 다 직접 돌려봤다.
| 기존 풀이 | 짧은 풀이 |
|---|---|
![]() | ![]() |
결과는 기존 풀이가 현저하게 좋다.
무조건 숏코딩 하려고 하지 말고, 어떤 코드가 효율적인지, 가독성이 좋은지 생각하면서 풀어야겠다는 생각을 했다.