Python

<Python> 진법 변환

Su_Do 2020. 11. 19. 15:43

문제


[1212번] 8진수 2진수 : www.acmicpc.net/problem/1212

8진수를 2진수로 변환하는 간단한 문제였다.

하지만 나는 진법 변환하는 문제를 처음 풀어보았고 파이썬 내장 함수에 대해서 모르고 있었다.

그렇기 때문에 브론즈 4문제 치고 많은 코드를 쓰게 되었다.


코드


[첫 번째 시도]

import sys

n = list(map(int, sys.stdin.readline().rstrip()))

def EightTwo(list):
    result = ''
    for i in range(len(list)):
        if list[i] == 0:
            result += '000'
        elif list[i] == 1:
            result += '001'
        elif list[i] == 2:
            result += '010'
        elif list[i] == 3:
            result += '011'
        elif list[i] == 4:
            result += '100'
        elif list[i] == 5:
            result += '101'
        elif list[i] == 6:
            result += '110'
        else:
            result += '111'

    return result

result = EightTwo(n)

while result[0] == '0':
    result = result[1:]

print(result)

 

위가 내 첫 번째 코드였다.

result에 한 숫자씩 2진수로 변환한 뒤 while문을 통해 제일 앞이 0이면 그 뒤부터를 다시 result에 저장하고 출력하는 알고리즘이었다.

 

하지만 이 코드는 시간 초과가 떴고 다른 사람들이 한 질문을 보다가 result라는 곳에 2진수로 변환한 수를 저장하지 말고 바로바로 출력하는 알고리즘을 사용하는 게 어떻냐는 답변을 보았다.

그 후 바로 코드를 다시 짜 보았다.

[두 번째 시도]

import sys

n = list(map(int, sys.stdin.readline().rstrip()))

def EightTwo(list):
    for i in range(len(list)):
        if list[i] == 0:
            if i == 0:
                print('0', end='')
            else:
                print('000', end='')
        elif list[i] == 1:
            if i == 0:
                print('1', end='')
            else:
                print('001', end='')
        elif list[i] == 2:
            if i == 0:
                print('10', end='')
            else:
                print('010', end='')
        elif list[i] == 3:
            if i == 0:
                print('11', end='')
            else:
                print('011', end='')
        elif list[i] == 4:
            print('100', end='')
        elif list[i] == 5:
            print('101', end='')
        elif list[i] == 6:
            print('110', end='')
        else:
            print('111', end='')

EightTwo(n)

 

사실 0을 입력받았을 때 0이 아닌 000을 출력해서 한 번 틀렸었다. 하지만 금방 오류를 잡았고 이 코드로 수정했다.

결과는 맞았다. 하지만 시간이 많이 소비되었고 나는 무언가 내가 잘못된 알고리즘을 사용하고 있다는 것을 깨달았다.

그래서 이 문제를 맞은 사람의 코드를 하나씩 보게 되었다.

 

맞은 사람들의 코드를 크게 나누면 3 분류였다.

bin으로 푼 사람, format으로 푼 사람, 나처럼 푼 사람들이었다.


알게 된 점


1. bin으로 푼 사람

print(bin(int(input(), 8))[2:])

 

딱 한 줄로 풀었다. 이 코드를 보고 아직 나는 햇병아리에 불과하다는 것을 알게 되었다.

 

먼저 int(input(), 8)에 대해서 알아보았다.

 

print(int(input()))
# 314 -> 314

print(int(input(), 2))
# 11 -> 3

print(int(input(), 8))
# 314 -> 204

print(int(input(), 16))
# 314 -> 788

 

int(a, b)는 b진수인 a를 10진수로 바꾸어 주는 함수였다.

즉, 8진수인 314를 10진수로 바꾸어주니 204가 된 것이다.

 

그다음 bin()에 대해서 알아보았다.

 

print(bin(int(input(), 8)))
# 314 -> 0b11001100

print(bin(int(input(), 8))[2:])
# 314 -> 11001100

 

bin(n)는 10진수인 n을 2진수 값으로 변환해 주는 함수였다.

2진수의 표현은 0b를 앞에 붙여서 쓰기 때문에 314를 그냥 bin()으로 출력하면 0b11001100이 나오게 된다.

그렇기 때문에 인덱스 2부터 끝까지 출력하기 위해 [2:]을 붙여서 쓰게 되면 원하는 답인 11001100이 나오게 된다.

 

참고로 아래는 8진수와 16진수 값으로 변환해 주는 함수다.

 

bin(n)
# 10진수인 n을 2진수 값으로 변환해 주는 함수
# 0b로 시작

oct(n)
# 10진수인 n을 8진수 값으로 변환해 주는 함수
# 0o로 시작

hex(n)
# 10진수인 n을 16진수 값으로 변환해 주는 함수
# 0x로 시작

 

2. format으로 푼 사람

print(format(int(input(), 8), 'b'))

 

앞서서 int(input(), 8)은 8진수인 입력된 값을 10진수로 변환해 주는 것이라는 걸 알았다.

그렇기 때문에 format(n, s)만 알면 된다.

format(n, s)는 10진수 n을 s에 들어가는 진수로 만들어 주는 함수다.

s에는 'b', 'o', 'x'가 들어갈 수 있다.

 

print(format(int(input(), 8), 'b'))
# 10진수를 2진수로 만들어주는 함수
# 314 -> 11001100

print(format(int(input(), 8), 'o'))
# 10진수를 8진수로 만들어주는 함수
# 314 -> 314

print(format(int(input(), 8), 'x'))
# 10진수를 16진수로 만들어주는 함수
# 314 -> cc

# format(n, s)에서 s 부분에 #을 붙여주면 접두어가 같이 출력된다

print(format(42, '#b'))
# 314 -> 0b11001100
print(format(int(input(), 8), '#o'))
# 314 -> 0o314
print(format(int(input(), 8), '#x'))
# 314 -> 0xcc

더 풀어볼 문제


[1373번] 2진수 8진수 : www.acmicpc.net/problem/1373

[1550번] 16진수 : www.acmicpc.net/problem/1550

[2998번] 8진수 : www.acmicpc.net/problem/2998

[3460번] 이진수 : www.acmicpc.net/problem/3460

[8741번] 이진수 합 : www.acmicpc.net/problem/8741

[10829번] 이진수 변환 : www.acmicpc.net/problem/10829

[11179번] 2진수 뒤집기 : www.acmicpc.net/problem/11179

[11816번] 8진수, 10진수, 16진수 : www.acmicpc.net/problem/11816