백준 2745번 풀이

문제

n진수 숫자를 10진수로 바꾸기

진수변환 수동으로 하는 법

아 이거… 10진수->n진수는 코딩한 게 있는데 반대 버전이 없어요…

https://github.com/koreanraichu/Python/blob/master/Dec%20to%20Bin.py

https://github.com/koreanraichu/Python/blob/master/Dec%20to%20Hex.py

https://github.com/koreanraichu/Python/blob/master/Dec%20to%20Oct.py

순서대로 2, 16, 8진수로 변환하는 코드. 그럼 이제 원리를 알려드림.

일단 n진수를 10진수로 변환할때는 일의자리부터 1, n, n^2, n^3, …이런 식으로 곱한 다음 더하면 된다. (0이면 패스) 10진수를 n진수로 바꿀 때는 n으로 더 이상 나누어 떨어지지 않을 때까지 나눈 다음 위 그림처럼 쓰면 된다. 10진수 이상일 경우 나머지가 10 이상일 때도 있는데 그건 알파벳 A부터 시작하면 된다. 16진수의 경우 A, B, C, D, E, F 순서대로 10, 11, 12, 13, 14, 15.

2, 8, 16진수 상호변환은 1) 뒤에서부터 세자리씩 끊어서 10진수로 변환(2->8), 2) 뒤에서부터 네자리씩 끊어서 10진수로 변환하고 10 이상은 해당하는 알파벳으로 변환(2->16), 3) 2진수로 변환 후 해당하는 자릿수만큼 끊어서 10진수로 변환(8<->16)하면 된다.

저거 풀면서 역변환 코딩한 거 있는데 그건 따로 털어드림. 역변환 따로 한 건 진수가 고정되어있는데 이번 문제는 2부터 36까지 범위가 지정된 변수이다. 그니까 3진수 9진수 이런거 들어올수도 있다 그죠? 그럼 어카냐고? 입력이 두 개가 되는거죠.

over_ten_list = list(range(65,91))
over_ten_number = list(range(10,36))

A~Z가 10~35까지라고 나와있는데 왜 두 리스트가 다 숫자가 들어가있냐고? 그건 로직에서 설명드림.

import sys

a, N = sys.stdin.readline().split()
N = int(N)

cipher = len(a)
a = a[::-1]
dec_number = 0

over_ten_list = list(range(65,91))
over_ten_number = list(range(10,36))

for i in range(cipher):
    try:
        dec_number += int(a[i]) * (N ** i)
    except:
        dec_number += over_ten_number[over_ten_list.index(ord(a[i]))] * (N ** i)

print(dec_number)

여기서 키포인트는 두개다. 첫번째는 예외처리이고 두번째가 ord()인데…

  1. 애초에 파이썬으로 입력 받자마자는 내가 숫자를 쓴거건 문자로 쓴거건 자료형이 문자열이다. 그럼 int로 변환해야 뭘 계산하든가 말든가 하잖음? 문자열 그대로 계산하면 컴퓨터가 미쳤습니까 휴먼? 한다. 그런데 숫자가 아닌 알파벳을 int로 변환하려고 하면? 또 미쳤습니까 휴먼? 한다. 그리고 알파벳은 뭐가 있어요? 그죠 아스키코드 번호 있잖아. 입력이 대문자인데 65~90까지가 대문자 알파벳을 지정하네? (LA에서 잡은 안농 이름이 저거)
  2. 저 리스트가 알파벳 대문자 아스키코드에 해당하는 번호가 들어간 리스트니까 ord()로 변환해서 리스트에서 몇번째인가를 찾고, 다시 그걸로 해당하는 숫자 리스트에서 인덱싱하면 숫자가 나오잖음. ASCII 리스트로 범위 만든거니까 일일이 타이핑하는 수고로움도 줄었다 이거죠.

그래서 1) 입력받은 문자를 하나씩 숫자로 변환해서 곱하되 2) 변환 못하는거면(알파벳이면) 리스트에서 아스키코드 번호로 찾아서 3) 해당하는 숫자 곱해라 가 된거임. 와 천잰데 귀차니즘이 이렇게 유용합니다