숫자를 인수로 받아 각 자릿수를 계속 더한 뒤, 결과가 한 자리 숫자가 되었을 때 그 값을 반환하는 함수를 작성해야 합니다.
예를 들어 88이 주어지면 먼저 8 + 8 = 16을 계산합니다. 16은 아직 두 자리 숫자이므로 다시 1 + 6 = 7을 계산하고, 7은 한 자리 숫자이므로 최종 결과로 7을 반환하면 됩니다.
접근 방법
구현 방법은 매우 간단합니다. 숫자가 9보다 크거나 -9보다 작은 동안, 즉 두 자리 이상인 동안 각 자릿수를 계속해서 더하는 재귀 함수를 작성하면 됩니다. 부호 관련 로직을 두 번 작성하지 않도록, 음수 여부는 별도의 매개변수로 처리하는 것이 핵심입니다.
동작 원리
- 먼저
Math.abs()를 사용해 숫자의 절댓값을 구합니다. - 숫자가 9보다 크면 문자열로 변환한 뒤
split("")으로 각 자릿수로 분리합니다. reduce()를 활용해 모든 자릿수의 합을 구하고, 그 결과값으로 함수를 재귀적으로 다시 호출합니다.- 숫자가 9 이하가 되면 저장해 둔 부호 정보에 따라 양수 또는 음수로 변환하여 반환합니다.
예제
const sumRecursively = (n, isNegative = n < 0) => {
n = Math.abs(n);
if(n > 9){
return sumRecursively(parseInt(String(n).split("").reduce((acc,val) => {
return acc + +val;
}, 0)), isNegative);
}
return !isNegative ? n : n*-1;
};
console.log(sumRecursively(88));
console.log(sumRecursively(18));
console.log(sumRecursively(-345));
console.log(sumRecursively(6565));출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
7 9 -3 4
88 → 16 → 7, 18 → 9, -345 → -12 → -3, 6565 → 22 → 4 순서로 자릿수의 합이 계산되어 최종적으로 한 자리 숫자가 반환된 것을 확인할 수 있습니다.
참고: 수학적 공식으로 O(1)에 해결하기
이 문제는 수학에서 '디지털 루트(digital root)'라고 불리는 개념과 동일합니다. 재귀 호출을 반복하는 대신 모듈로 연산을 활용하면 상수 시간 안에 결과를 구할 수 있습니다.
const digitalRoot = n => {
if(n === 0) return 0;
if(n < 0) return -digitalRoot(-n);
return 1 + (n - 1) % 9;
};
console.log(digitalRoot(88)); // 7양수 n의 디지털 루트는 1 + (n - 1) % 9 공식으로 바로 계산할 수 있으므로, 성능이 중요한 환경에서는 이 방식을 고려해 볼 만합니다.