문제 정의
팩토리얼 진법(계승 진법)은 숫자의 거듭제곱이 아닌 팩토리얼을 밑으로 사용하여 수를 표현하는 독특한 기수법입니다.
이 체계에서 가장 오른쪽 자릿수는 항상 0이며 0!(=1)을 밑으로 합니다. 그 앞 자릿수는 0 또는 1만 가능하고 1!을 밑으로 하며, 다시 그 앞 자릿수는 0, 1, 2 중 하나이고 2!를 밑으로 합니다. 일반적으로 뒤에서 n번째 자릿수는 항상 0부터 n 사이의 값이며 n!을 밑으로 사용합니다.
이 문제를 해결하려면 두 개의 함수가 필요합니다. 첫 번째 함수는 10진수를 입력받아 팩토리얼 진법 표현 문자열을 반환하고, 두 번째 함수는 팩토리얼 진법 문자열을 입력받아 원래의 10진수 값으로 되돌려줍니다.
예를 들어, 10진수 463은 "341010"으로 인코딩됩니다. 그 이유는 다음과 같습니다.
463 = 3×5! + 4×4! + 1×3! + 0×2! + 1×1! + 0×0!
구현 예제
다음은 이를 구현한 JavaScript 코드입니다.
const num = 463;
const decimalToFact = (num = 1) => {
const legend = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
let str = '0';
let i = 2;
while(num){
str = legend[num%i] + str;
num = Math.floor(num / i);
i++;
};
return str;
};
const factToDecimal = (str = '') => {
const legend = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const l = str.length;
return str
.split('')
.reduce((a,e,i) => Number(a) * (l - i) + legend.indexOf(e), 0);
};
const fact = decimalToFact(num);
const dec = factToDecimal(fact);
console.log(fact);
console.log(dec);
코드 동작 원리
decimalToFact 함수: i를 2부터 시작하여 num을 i로 나눈 나머지(num % i)로 현재 자릿수를 구하고, 몫으로 num을 갱신한 뒤 i를 1씩 증가시키는 방식으로 각 자릿수를 차례대로 추출합니다. legend 배열 덕분에 10 이상의 자릿수도 A, B, C처럼 문자로 표현할 수 있어 큰 수도 처리 가능합니다.
factToDecimal 함수: 호너 방식(Horner's method)을 활용해 각 자릿수를 왼쪽부터 순회하면서 누적값에 자릿수 가중치를 곱하고 현재 자릿수를 더하는 reduce 연산으로 원래의 10진수를 복원합니다.
실행 결과
콘솔 출력 결과는 다음과 같습니다.
341010 463