본문 바로가기
Project Euler

Problem 17 - Number letter counts (2)

by 청양호박이 2020. 12. 10.

이번에는 기존의 문제를 좀 뒤틀어서 생각해 보겠습니다. 기존 문제는 요약을 하자면 내가 원하는 범위의 숫자에 대해서 알파벳으로 전환하여 그 길이를 모두 더한 결과를 출력하는 문제였습니다. 그렇다면, 기왕해보는 김에 숫자를 입력하면 string으로 출력해주는 프로그램을 만들어 보면 어떨까요??

 

이름하여, 숫자에 대한 문자변환기... 가 되는것이죠.

 

숫자 1 ~ 5에 대해서 문자로 변환하면, 말 그대로 One, Two, Three, Four, Five 로 변환이 되게 됩니다. 그렇다면, 어마어마하게 큰 숫자는 어떻게 변환이 가능할까요??

 

예를들어, 104382426112라는 숫자가 있다면... 10조이상에 해당하는 숫자로... 영문자로 변환을 한다면,

One Hundred Four Billion Three Hundred Eighty Two Million Four Hundred Twenty Six Thousand One Hundred 

Twelve (길어서 잘리네요...)

 

영어에는 몇가지 규칙이 있습니다.

 

  • 가장 뒤의 숫자를 기준으로 3자리씩 잘라서 읽을 수 있으며, 각 3자리는 동일한 로직으로 변환합니다.
  • 3자리씩 잘라서 올라갈때마다 추가로 단위가 붙게되고, 그 단위는 각 3자리에 대해서 읽고 추가로 붙여주기만 하면 됩니다. 
  • 10단위의 자리를 변환 할 때는 11~19까지 고유한 단어를 사용하기 때문에 살짝 고민이 필요합니다.

 

이정도만 생각하면 구현이 가능합니다.

 

 

1. Basic


위의 예를들어서 설명을 해보면.... 104382426112 일때 

 

[단계1] : 뒤에서부터 3자리씩 잘라서 일단 단위에 고민없이 변환합니다.

구분 변환
104 One Hundred Four
382 Three Hundred Eighty Two
426 Four Hundred Twenty Six
112 One Hundred Twelve

[단계2] : 단위를 고려해 봅니다.

구분 변환
4번째 Billion
3번째 Million
2번째 Thousand
1번째 -

이제 각 행에 맞게 합쳐만 주면 됩니다.

 

[단계3] : 10단위의 자리를 변환 할 때는 이전글을 참조부탁드립니다. 

2020/12/08 - [Project Euler] - Problem 17 - Number letter counts (1)

 

그럼 최종코드를 확인해 보겠습니다.

 

[소스 코드]

import time

if __name__ == '__main__':
    start = time.time()

    num_dict = {0: '', 1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', 5: 'Five', 6: 'Six', 7: 'Seven', 8: 'Eight',
                9: 'Nine',
                10: 'Ten', 11: 'Eleven', 12: 'Twelve', 13: 'Thirteen', 14: 'Fourteen', 15: 'Fifteen', 16: 'Sixteen',
                17: 'Seventeen', 18: 'Eighteen', 19: 'Nineteen',
                20: 'Twenty', 30: 'Thirty', 40: 'Forty', 50: 'Fifty', 60: 'Sixty', 70: 'Seventy', 80: 'Eighty',
                90: 'Ninety'}

    big_dict = {0: '', 1: ' Thousand', 2: ' Million', 3: ' Billion'}

    tc = int(input())
    for t in range(tc):
        inp = int(input())
        cnt = 0
        res = ''
        while inp % 1000 != 0:
            remains_3 = inp % 1000
            remains_2 = remains_3 % 100
            res = big_dict[cnt] + res

            mok = remains_2 // 10
            remains = remains_2 % 10
            set = remains_2 - remains

            # 10단위 처리
            if mok == 0:
                res = ' ' + num_dict[remains] + res
            elif 11 <= remains_2 <= 19 or remains == 0:
                res = ' ' + num_dict[remains_2] + res
            else:
                res = ' ' + num_dict[set] + ' ' + num_dict[remains] + res

            # 100단위 처리
            if remains_3 // 100 != 0:
                res = ' ' + num_dict[remains_3//100] + ' Hundred' + res

            # big_dict 출력을 위해서 10^3 단위마다 +1 수행
            cnt += 1
            inp = inp // 1000

    print("결과 : ", res.strip())

코드는 특별한 것은 없습니다. 10^3에 해당하는 부분을 뒤에서부터 나누어서 변환을 수행하고, cnt 변수를 기준으로 단위를 출력해 줍니다. 이때, 10^3을 잘라내는 단계가 진행될때마다 +1을 함으로써 big_dict 를 통해서 단계에 맞는 단위를 포함하여 출력해 줍니다.

 

[결과]

13
1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111
11111111111
111111111111
104382426112
==========================================================================

결과 :  One
결과 :  Eleven
결과 :  One Hundred Eleven
결과 :  One Thousand One Hundred Eleven
결과 :  Eleven Thousand One Hundred Eleven
결과 :  One Hundred Eleven Thousand One Hundred Eleven
결과 :  One Million One Hundred Eleven Thousand One Hundred Eleven
결과 :  Eleven Million One Hundred Eleven Thousand One Hundred Eleven
결과 :  One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven
결과 :  One Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven
결과 :  Eleven Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven
결과 :  One Hundred Eleven Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven
결과 :  One Hundred Four Billion Three Hundred Eighty Two Million Four Hundred Twenty Six Thousand One Hundred Twelve
소요시간 :  0.8670001029968262

정상적으로 동작하는 것을 확인했습니다. 

 

- Ayotera Lab -

댓글