-
[8일차](문제 번호 : 11005, 진법 변환 2) 도전 -2백준 문제 풀이 2023. 7. 27. 10:13
1. 오류 이유
저번 풀이에서 NameError가 발생했었다.
이는 주로 변수 선언이 안된 상태에서 그 변수를 사용했을 때, 발생한다고 했다.
N, B = map(int, input().split()) for i in range(30): if N <= B**i: M = i break
그리고 추정끝에, N = 1000000000 (최댓값) B =2 를 넣었을 때, NameError 가 발생했다.
그 이유는 range(30)이 30을 포함하지 않기 때문에 i는 최대 29이고, 2^29은 약 5억이기때문에,
5억 이상의 수들을 2진법으로 표현할 때, 오류가 발생했던 것이다.
따라서 range(31)로 수정했다.
또한, N = 1 or 0 일 때의 계산도 간편하게 하기 위해 아래의 식을 도입했다.
BBase = [] if M != 0: for i in range(M)[::-1]: for j in range(37): if N - j*B**i < 0: BBase.append(j-1) N -= (j-1)*B**(i) break elif N == 1: BBase.append(1) else: BBase.append(0)
새로 추가된건 elif 부분부터이다. M = 0 이라면, N = 1or0 이기 때문이다.
그런데..
2. 새로운 문제
채점 결과.. 오류는 발생하지 않았지만, 계산 결과가 틀렸다.
어딘가 논리적 결함이 있었다.
먼저, 찾아낸 if N - j*B**i < 0 조건 식에서, ==0 일 때의 상황도 고려했어야했다.
즉, 아래의 식을 추가로 삽입하였다.
elif N - j*B**i == 0: BBase.append(j) for k in range(i): BBase.append(0) N=1000000000000 break
N을 10억을 훨씬 초과하는 큰 수로써 바꾸는 이유는 만약 == 0 상황에서는
B진법으로 바꿀 때, 재귀의 식을 고려하지않고, 남은 자리는 0으로 매꾸어 작성하면 되는 것이기 때문이다.
(즉, if문을 더 이상 성립시켜 재귀식을 성립하지않게 하려고)
다음으로 range의 범위도 아래와 같이 바꾸었다.
for i in range(0,M+1)[::-1]:
다음으로, 위의 range 범위를 바꾸었다보니, 첫자리가 0이 되어버렸다.
B진법수로 바꾸었을 때, 일반적인 정수(0을 제외)는 맨 앞자리가 0이 되면 안되므로,
아래의 식을 추가하여 앞자리의 0을 제거하였다.
while BBase[0] == '0' and len(BBase) != 1: BBase = BBase.lstrip('0')
3. 개선 방안
맞힌 사람들의 정답 코드를 쓱 보니, int() 함수에 이러한 진법 변환 기능은 없는 것 같고,
나보다 훨씬 깔끔한 논리로써 코드를 작성하였다.
예를 들어 N = 23*36^3 + 18*36^2 + 35*36^1 + 35*36^0 = 139040 , B = 36 이라고 하면,
N%B = 35이다.(진법수의 마지막 자리)
N//B = 23*36^3 + 18*36^2 + 35*36^1 이다.
위의 값을 N으로 지정하고 계속 반복하면 된다.
나도 처음에는 이런 논리로 생각했었는데, 왜인지 모르겠지만.. 포기했었다.
좀 더 해볼껄 그랬다.
개인사정으로 글을 며칠간 못올렸다. 이로 인해 학교 행사에는 제대로 참여하지 못했지만,
오늘 추가적으로 더 풀어야겠다는 생각이 든다.
'백준 문제 풀이' 카테고리의 다른 글
[열 번째](문제 번호 : 2869, 달팽이는 올라가고 싶다) 도전 (0) 2023.08.03 [7일차](문제 번호 : 11005, 진법 변환 2) 도전 -1 (0) 2023.07.24 [6일차](문제 번호 : 2745, 진법 변환) 도전 (0) 2023.07.23 [5일차](문제 번호 : 2536, 색종이) 도전 (0) 2023.07.22 [4일차](문제 번호 : 2566, 최댓값) 도전 (0) 2023.07.21