반응형

 진법은 항상 귀찮습니다. 예를 들어 10진수의 '12345'의 값을 10진수로 출력하거나, 16진수의 '12345'의 값을 10진수로 출력하거나. 이 귀찮음을 해결할 방법이 없을까요? 파이썬에는 int가 있습니다. 사실 저는 단순히 문자열을 정수로 변환하기 위해서 쓰는 줄로만 알았습니다. 이걸 잘 이용하면 k진수를 10진수로 바꿀 때, 대소문자가 오는 경우에 자릿수를 계산하는 귀찮은 처리를 덜 수 있습니다.

 


 예제 몇 개를 보면서 이해해 보도록 하겠습니다. 먼저, 36진수로 표현된 'abcde', 'ABCDE'를 10진수로 바꿉니다. 다음에, 2진수로 표현된 '10110'을 10진수로 바꿉니다.

 

 여기서, base 인자가 들어간 것이 있고, 들어가지 않은 게 있습니다. base 인자가 들어가면, 1번째 인자로 표현된 것이 base 진수로 표현된 것이라는 의미입니다. 그런데, 4번째 인자에는 아무것도 들어가지 않았는데요. 이 경우는 base가 10이라고 간주합니다. 즉, 5번째 줄의 실행 결과는 10110이 나옵니다.

 

 위 그림은 실행 결과입니다.

 


 이제 다른 예제를 보도록 합시다. 숫자나 대소문자로 표현된 string이 있습니다. 이것이 n진수로 표현이 된 거라고 해 봅시다. n의 범위는 어떻게 될까요? 예를 들어, '12345'는 5진수로 표현이 된 것은 아닙니다. 6진수로는 표현할 수 있어요. 5는 6보다는 작기 때문입니다. 이걸 구할 때에는, max 함수를 이용하는 게 편합니다.

 

 그런데, 단순히 max만 고려하면 될까요? 사실 반례가 있습니다. '12abZ'와 같이 대소문자가 섞여 있는 경우에 잘못 동작할 수도 있습니다. 이는 문자 'Z'가 문자 'b'보다 ascii 코드 값이 작기 때문입니다. 실제로, 이 프로그램을 실행하면, 예외가 떡하니 뜨는데요.

 

 invalid literal ~ with base 12라고 뜹니다. 0, 1, 2, 3, ... , 9, a, b, c, ... 순서대로 올라간다 했을 때 'b'의 값은 11입니다. 여기에 1을 더했으니 12입니다. 이 값이 들어갔는데, Z는 26 + 9 = 35입니다. 35는 12진법에서는 사용될 수 없으니 ValueError가 뜨는 게 맞습니다.

 

 

 그러면 어떻게 해야 할까요? replace를 이용하면 됩니다. 문제가 되었던 것은 대소문자가 혼용되어 있는 경우이니, 모든 대문자를 소문자로 바꾸거나, 아니면 역방향으로 바꾸면 됩니다.

 

 위 프로그램은 이 방법으로 '12abZZ'에 대해서 올바른 값을 도출해 냅니다. 보시면, 대문자를 모두 소문자로 바꾸었음을 알 수 있습니다. replace는 문자열 처리에서 생각보다 많이 쓰이니, 알아두시는 게 좋겠습니다.

 

 

 결과가 제대로 나오네요.

 


 이제 이 문제를 생각해 보겠습니다.

 

 

 A와 B의 진법을 2부터 36까지 돌립니다. 여기서 valid한 경우가 생길 수 있어요. 예를 들자면 s1이 "234"인데 i값이 2인 경우, 올바르지 않습니다. 그러므로 ValueError가 뜰 텐데요. 이 때 예외를 잡습니다. 예외가 발생하지 않았다면, 문제에서 설명하는 조건이 맞아 떨어지면, ans에 append를 합니다.

 

 다음에 조건에 따라서 답을 출력합니다. 그런데, 의문점이 드는 것은 범위 체크를 하는데, 예외를 굳이 잡아야 할까? 우리에게 필요한 것은 범위 체크임을 알 수 있어요. 그 처리를 하기 위해서 예외를 잡아서, catch가 되면 무시해 버린다. 좋은 방법인지 잘 모르겠어요. 두 번째 의문은 'zz', 'zz'인 경우에도 35^2가지의 모든 경우에 대해서 탐색을 해야 하느냐입니다.

 

 

 소문자와 숫자만 주어진다고 하면, 단순하게, 문자열 s1에서의 최댓값을 가져 오면 됩니다. 먼저. 예를 들어 '01c'가 들어왔다면, 'c'가 최댓값이 될 거고, int('c', 36)을 하면, 'c'의 값이 나올 것이기 때문입니다. 'z'라고 해 봤자 35보다 작기 때문에, 36으로 두었습니다. 그러면, 진법은 'c'가 최대인 경우, 'c' 값이 12인데요. 'c'는 12진법에 있을 수 없는 수입니다. 13진법부터 있을 수 있어요. 그래서, 2번째 줄과 3번째 줄에, +1을 해 주었습니다.

 

 

 이 값을 가지고, 2중 for loop를 돌려주면 하면 됩니다. 0진법, 1진법은 없으므로, max(2, z1), max(2, z2) 처리를 해 주었습니다.

반응형

댓글을 달아 주세요