백준 2745번을 풀어보았다.
크게 3가지 풀이로 정리할 수 있다.
- 0~9, A~Z로 케이스 구분 후 계산
- parseInt 메소드
- reverse 메소드
1. 0~9, A~Z로 케이스 구분 후 계산
이때 0~9, A~Z로 케이스를 구분하는 방법에 따라 크게 3가지로 구분할 수 있다.
1-1. isNaN 메소드
let [N, B] = require('fs').readFileSync('/dev/stdin').toString().split(' ')
B = Number(B)
let decimal = 0, exponent = 0
for (let i = N.length - 1; i >= 0; i--) {
let value = 0
if (isNaN(N[i])) value = N[i].charCodeAt() - 55
else value = Number(N[i])
decimal += value * Math.pow(B, exponent++)
}
console.log(decimal)
1-1 풀이는 N[i]의 자료형이 숫자인지, 문자인지로 0~9, A~Z 케이스를 구분한다.
처음에는 if (Number(N[i])) === undefined) 로 작성하였는데, 이는 두 가지 점에서 잘못됐다.
- Number(문자)는 undefined가 아니라 NaN이다.
- NaN은 비교 연산자로 비교할 수 없다.
즉, if (isNaN(N[i])) 로 작성해야 한다.
아래 예시를 잘 기억해두자.
> Number('a')
NaN
> Number('a') === NaN
false
> isNaN(Number('a'))
true
1-2. charCodeAt 메소드
let [N, B] = require('fs').readFileSync('/dev/stdin').toString().split(' ')
B = Number(B)
let decimal = 0, exponent = 0
for (let i = N.length - 1; i >= 0; i--) {
let value = 0
if (N[i].charCodeAt() >= 65) value = N[i].charCodeAt() - 55
else value = Number(N[i])
decimal += value * Math.pow(B, exponent++)
}
console.log(decimal)
1-3. 값 직접 비교
let [N, B] = require('fs').readFileSync('/dev/stdin').toString().split(' ')
B = Number(B)
let decimal = 0, exponent = 0
for (let i = N.length - 1; i >= 0; i--) {
let value = 0
if ('A' <= N[i] && N[i] <= 'Z') value = N[i].charCodeAt() - 55
else value = Number(N[i])
decimal += value * Math.pow(B, exponent++)
}
console.log(decimal)
2. parseInt 메소드
let [N, B] = require('fs').readFileSync('/dev/stdin').toString().split(' ')
B = Number(B)
let decimal = parseInt(N, B)
console.log(decimal)
parseInt 메소드는 문자열을 정수형 숫자로 변환하는 기능, n진법을 10진법으로 변환하는 기능을 수행하며
이 중 진법 변환 기능을 사용하여 문제를 해결할 수 있다.
> parseInt('1')
1
> parseInt('1.2')
1
> parseInt('a')
NaN
> parseInt('1a')
1
> parseInt('a1')
NaN
> parseInt(' 1 ')
1
> parseInt('101', 2)
5
> parseInt('1f', 16)
31
3. reverse 메소드
let [N, B] = require('fs').readFileSync('/dev/stdin').toString().split(' ')
B = Number(B)
N = N.split('').reverse()
let decimal = 0
let number = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for (let i = 0; i < N.length; i++) {
let value = number.indexOf(N[i])
decimal += value * Math.pow(B, i)
}
console.log(decimal)
N의 인덱스(i)가 커질수록 B의 차수(exponent)는 커진다.
이러한 이유로 1번 풀이에서는 exponent를 따로 정의하였는데, (exponent를 사용하지 않고도 풀이할 수 있지만, 식이 복잡해질 것 같아)
reverse 메소드를 사용해 N을 뒤집어버리면 exponent를 정의하지 않고 i만으로도 간단하게 풀이할 수 있다.
💫 이 문제를 통해 배운 것
숫자 자료형 여부는 isNaN 메소드로 확인한다.