두 정수 left와 right가 매개변수로 주어집니다. left부터 right까지의 모든 수들 중에서, 약수의 개수가 짝수인 수는 더하고, 약수의 개수가 홀수인 수는 뺀 수를 return 하도록 solution 함수를 완성해주세요.
1 ≤ left ≤ right ≤ 1,000
left | right | result |
---|---|---|
13 | 17 | 43 |
24 | 27 | 52 |
입출력 예 #1
다음 표는 13부터 17까지의 수들의 약수를 모두 나타낸 것입니다.
수 | 약수 | 약수의 개수 |
---|---|---|
13 | 1, 13 | 2 |
14 | 1, 2, 7, 14 | 4 |
15 | 1, 3, 5, 15 | 4 |
16 | 1, 2, 4, 8, 16 | 5 |
17 | 1, 17 | 2 |
따라서, 13 + 14 + 15 - 16 + 17 = 43을 return 해야 합니다.
다음 표는 24부터 27까지의 수들의 약수를 모두 나타낸 것입니다.
수 | 약수 | 약수의 개수 |
---|---|---|
24 | 1, 2, 3, 4, 6, 8, 12, 24 | 8 |
25 | 1, 5, 25 | 3 |
26 | 1, 2, 13, 26 | 4 |
27 | 1, 3, 9, 27 | 4 |
따라서, 24 - 25 + 26 + 27 = 52를 return 해야 합니다.
//약수의 개수를 구하는 함수를 만들어 줌
function countDivisor(num){
let sum = 0;
for(let i = 0; i <= num; i++ ){
if (num % i === 0)
sum += 1;
}
return sum;
}
//left보다 크거나 같고 right보다 크거나 같은 숫자의 약수 개수를 구해줌
//약수 개수가 짝수라면 +, 홀수라면 -해줌.
function solution(left, right) {
let divisorSum = 0;
for(let i = left; i<= right; i++ ){
countDivisor(i) % 2 === 0 ? divisorSum += i : divisorSum -= i;
}
return divisorSum;
}
이 풀이도 결과가 이상하게 나와서 한참 헤맸다. countDivisor(num)
함수는 제대로 작동하는데 solution(left, right)
이 제대로 작동하지 않았다. 알고보니 반복문 for에서 i의 변수 선언을 안 해줬기 때문이었다.
i = 0;
여태까지 for의 초기문을 이런 식으로 적어줬는데, 오류가 발생한 적이 없었다. 그래서 초기값의 변수를 선언하지 않아도 괜찮은 줄 알았는데, 반복문을 두 번 쓰면서 변수 i를 여러 번 쓰니 문제가 발생했다.
이러한 문제가 발생한 이유는, 변수를 선언하지 않았을 때, 자바스크립트는 변수를 var같은 전역변수로 지정해 주기 때문이다.
위의 변수 i와 아래의 변수 i는 전혀 다른 변수인데 전역변수로 지정하면서 똑같은 변수로 취급해서 문제가 발생한 것이다. 따라서 for 반복문의 초기문에서 반드시 변수 선언을 해 줘야하며, 선언을 할 때도 var이 아닌 let으로 선언해 줘야 한다.
let i = 0;
function solution(left, right) {
var answer = 0;
for (let i = left; i <= right; i++) {
if (Number.isInteger(Math.sqrt(i))) {
answer -= i;
} else {
answer += i;
}
}
return answer;
}
약수의 개수를 구하는 손쉬운 방법이 있을 것 같은데 결국 찾지 못했다. 소인수분해도 생각했으나 소인수분해를 하는 것 보다는 위의 풀이가 나을 것 같아 위처럼 풀어 줬다. 하지만 손쉬운 방법은 언제나 있었다.
이 풀이는 약수의 개수는 기본적으로 짝수인데, 어떤 수의 제곱인 경우에만 약수의 개수가 홀수임을 이용하여 풀어준 것이다. 약수는 원래 나누어 떨어지는 수이므로 각각 곱해서 원래 수가 되는 짝이 있다. 하지만 제곱수인 경우는 자기 자신을 두 번 곱하기 때문에 약수가 홀수가 되는 것이다.
예를 들어 16의 경우, 약수는 [1,2,4,8,16]인데, [1,16], [2,8]은 각각 곱하면 16이 되는 짝이다. 4같은 경우는 4 스스로를 다시 곱해야 16이 되므로 짝이 없게 된다. 그래서 결국 제곱수는 홀수개의 약수를 갖게 된다.
따라서 숫자가 제곱수인지 판별을 하면 약수가 짝수인지 홀수인지 알 수 있다. math.sqrt()
함수는 루트를 씌워주는 함수인데, 루트를 씌운 다음 Number.isInteger()
으로 정수인지 확인한다면 제곱수는 true, 나머지는 false를 인출할 것이다. 따라서 true라면 -i로, false라면 i로 만들어 주면 된다.