본문 바로가기
알고리즘 Node.js

백준 2745문제. 진법 변환(일반수학1 시작!)

by 반갑조? 2025. 4. 3.

문제

문제: B진법 수 N이 주어진다. 이 수를 10진법으로 바꿔 출력하는 프로그램을 작성하시오.

10진법을 넘어가는 진법은 숫자로 표시할 수 없는 자리가 있다. 이런 경우에는 다음과 같이 알파벳 대문자를 사용한다.

A: 10, B: 11, ..., F: 15, ..., Y: 34, Z: 35

입력: 첫째 줄에 N과 B가 주어진다. (2 ≤ B ≤ 36). B진법 수 N을 10진법으로 바꾸면, 항상 10억보다 작거나 같다.

출력: 첫째 줄에 B진법 수 N을 10진법으로 출력한다.

예제 입력: ZZZZZ 36

예제 출력: 60466175

 

풀이(왼 → 오)

const fs = require('fs');
const [N, B] = fs.readFileSync(0, 'utf-8').trim().split(' ');

const base = Number(B); // 문자열 '36'을 숫자 36으로 변환.
console.log(typeof base,'base'); // Number

// 누적합 저장 변수
let result = 0;

// 왼쪽에서 오른쪽으로 순회
for(let i = 0; i < N.length; i++){
  const c = N[i];
  console.log(c,'c'); // 'N'
  
  // 문자에서 숫자로 변환
  let value = 0;
  if (c >= 'A') {
   value = c.charCodeAt(0) - 55; // A~Z → 10~35
  } else {
   value = c.charCodeAt(0) - 48; // 0~9 → 0~9
  }
  
  // 자릿수 반영해서 누적합을 계산한다.
  result = result * base + value;
}

// 결과 출력
console.log(result)
더보기

for문의 if문을 이렇게 표현하면 좀 더 명확해진다.

if(c >= '0' && c<='9'){ // c가 0~9라면 숫자이니까
    value = c.charCodeAt(0) - '0'.charCodeAt(0); // 실제 숫자
  }else{ // 문자열 a~z라면
    value = c.charCodeAt(0) - 'A'.charCodeAt(0) + 10 // 90 - (65+10) = 35 ===36진법의 Z
  }

풀이 해석(숫자를 쌓아가는 방식)

1. 백준 표준 입력을 사용해서 데이터를 읽는다. trim()으로 앞뒤 공백을 제거하고 split(' ')으로 공백을 기준으로 나눈 값을 각각 N과 B로 저장한다.

2. B는 숫자로 변환한다.

3. 결과값을 저장한 변수 result를 선언한다.

4. for문을 사용하여 문자열 N의 왼쪽부터 한 글자씩 꺼내와서 변수 c에 저장한다.

5. 만약 c문자가 A보다 크면 알파벳이므로 c문자의 charCodeAt(0) -55를 해서 36진법 숫자와 맞춘다.

6. c문자가 A보다 크지 않다면 숫자이므로 -48을 해준다.

7. result에 자릿수를 반영해서 값을 점점 누적해 나간다.★

  - 예) '1A' 16진법일 경우

     첫 글자: '1' → 1 → result = 0 * 16 + 1 = 1

     두 번째: 'A' → 10 → result = 1 * 16 + 10 = 26

     이런식으로 자릿수를 반영해서 점점 값을 누적해 나간다!

8. 최종 계산된 10진법 값을 출력한다.

 

더 알아보기

1. 왼 → 오로 자릿수 계산하는 방식(거듭제곱)

const fs = require('fs');
const [N, B] = fs.readFileSync(0, 'utf-8').trim().split(' ');

const base = Number(B);
let result = 0;
const len = N.length;

for (let i = 0; i < len; i++) {
  const c = N[len - 1 - i]; // 오른쪽부터 읽기 (역순)
  let value;

  if (c >= '0' && c <= '9') {
    value = c.charCodeAt(0) - 48;
  } else {
    value = c.charCodeAt(0) - 55; // A=65 → 65 - 55 = 10
  }

  result += value * (base ** i);
}

console.log(result);

  - len-1-i : 오른쪽부터 한 글자씩 읽기 위한 인덱스

  - value*(base ** i) : 자릿수에 해당하는 값 계산(거듭제곱)

  - result += ... : 누적 합 계산

 

2. 오 → 왼 VS 왼 → 오 비교

  - 오 → 왼: 수학적인 계산 원리를 그대로 쓰는 것.

  - 왼 → 오: 빠르고 직관적.

 

3. 10진법 숫자 '60466175'를 N진법으로 바꾸기

- 순서

  a. 60466175 / 36 = 몫 + 나머지

  b. 몫을 다시 36으로 나눔

  c. 나머지들을 뒤에서부터 모아줌

*핵심 공식*
while (숫자 > 0):
    나머지 = 숫자 % 진법
    결과 앞에 추가
    숫자 = Math.floor(숫자 / 진법)
const fs = require('fs');
const [N, B] = fs.readFileSync(0, 'utf-8').trim().split(' ');

let num = parseInt(N); // 10진수
const base = parseInt(B);
let result = '';

while (num > 0) {
  const remainder = num % base;

  // 숫자가 0~9면 그대로, 10~35면 A~Z로 변환
  const digit = remainder < 10 
    ? String(remainder) 
    : String.fromCharCode(remainder + 55);

  result = digit + result;
  num = Math.floor(num / base);
}

console.log(result);
계속 36으로 나누면 : 
60466175 % 36 = 35 → 'Z'
1679615 % 36 = 35 → 'Z'
46655 % 36 = 35 → 'Z'
1295 % 36 = 35 → 'Z'
35 % 36 = 35 → 'Z'
따라서 결과는 'ZZZZZ'가 된다.

- String.fromCharCode() 설명

  - 숫자 10 → 'A' = 10+55=65 → 'A'.charCodeAt(0) = 65

  - 숫자 35 → 'Z'.charCodeAt(0) = 90

  그래서 String.fromCharCode(10+55) → 'A'