파이썬 실전 프로젝트

프로젝트 오일러 17번문제 - 숫자-알파벳 변환후 글자수카운트

토픽 파이썬 실전 프로젝트 > 파이썬 실전프로젝트

 1부터 1000까지의 숫자를 영어표기법 단어로 바꾼후에, 글자수를 세는 문제입니다.

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

 

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out numbers is in compliance with British usage.

 

1. 정석대로 푸는 방법이 있고,

2. num2words  라는 파이썬 라이브러리를 이용하는 방법도 있습니다.

 

먼저, 정석대로 풀어보면,

영어표기법중 and를 넣는 부분이 좀 헷갈립니다. 100이상부터는 무조건 백과 십자리 사이에 and를 넣어준다는군요.

one two three four five six seven eight nine ten
eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen
twenty thirty forty fifty sixty seventy eighty ninety hundred thousand 

"and, hundred, thousand" 외의 숫자는 딕셔너리 타입에 저장해놓고, 불러서 조합해주겠습니다.

{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'}

 

딕셔너리 만들기

딕셔너리 타입은 직접 타이핑해도 되지만, 명령어로 생성하는게 편합니다.

data1=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
       30,40,50,60,70,80,90]
data2='''one two three four five six seven eight nine ten 
eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen
twenty thirty forty fifty sixty seventy eighty ninety'''
numbers=dict(zip(data1,data2.split()))

dict() : 딕셔너리 타입 생성

zip() : 나열형의 자료형 두개를 짝으로 만들어서 묶어줍니다. 딕셔너리를 만들거나, 루프문을 돌릴때 사용합니다.

 

20까지 출력
total=0
for i in range(1,21):
    total+=len(numbers[i])
    print(i,numbers[i],len(numbers[i]),total)
1 one 3 3
2 two 3 6
3 three 5 11
4 four 4 15
5 five 4 19
6 six 3 22
7 seven 5 27
8 eight 5 32
9 nine 4 36
10 ten 3 39
11 eleven 6 45
12 twelve 6 51
13 thirteen 8 59
14 fourteen 8 67
15 fifteen 7 74
16 sixteen 7 81
17 seventeen 9 90
18 eighteen 8 98
19 nineteen 8 106
20 twenty 6 112

20까지는 딱히 조합할것이 없기 때문에, 변수에 있는 데이터를 그대로 출력해주면 됩니다.

 

100까지 출력
def func(num):
    if (num) not in numbers:
        numbers[num] = numbers[num-num % 10] + numbers[num % 10]
    return numbers[num]

total=0
for i in range(1,100):
    value=func(i)
    total+=len(value)
    print(i,value,len(value),total)
1 one 3 3
2 two 3 6
3 three 5 11
4 four 4 15
5 five 4 19
6 six 3 22
7 seven 5 27
8 eight 5 32
....
...
91 ninetyone 9 773
92 ninetytwo 9 782
93 ninetythree 11 793
94 ninetyfour 10 803
95 ninetyfive 10 813
96 ninetysix 9 822
97 ninetyseven 11 833
98 ninetyeight 11 844
99 ninetynine 10 854

20이후부터 조건문으로 나눠줄수도 있지만, 코드를 약간 수정하면, 100까지 같은 조건문 내에서 계산할수 있습니다. 기존에 저장된 값이 있는지 없는지에 따라서, 있으면 불러서 사용하고, 26처럼 없는 수면 조합해서 20 + 6으로 나누어서 twenty + six 이런식입니다.

그리고 새로 조합한 숫자는 딕셔너리에 추가로 저장하도록 했습니다. 100이상 넘어가면 다시 불러써 써야되니깐요.

 

1000까지 계산
def func(n):
    if n <100:
        if (n) not in numbers:
            numbers[n] = numbers[n - n % 10] + numbers[n % 10]
        return numbers[n]
    if n <1000:
        if n0==0:
            return  numbers[n//100] +  numbers[100]
        return numbers[n//100] +  numbers[100] + 'and' + numbers[n % 100]
    return 'one' + numbers[1000]

total=0
for i in range(1,1001):
    value=func(i)
    total+=len(value)
    print(i,value,len(value),total)
1 one 3 3
2 two 3 6
3 three 5 11
4 four 4 15
...
24 twentyfour 10 151
25 twentyfive 10 161
26 twentysix 9 170
27 twentyseven 11 181
28 twentyeight 11 192
29 twentynine 10 202
30 thirty 6 208
31 thirtyone 9 217
...
98 ninetyeight 11 844
99 ninetynine 10 854
100 onehundred 10 864
101 onehundredandone 16 880
102 onehundredandtwo 16 896
103 onehundredandthree 18 914
104 onehundredandfour 17 931
105 onehundredandfive 17 948
...
996 ninehundredandninetysix 23 21039
997 ninehundredandninetyseven 25 21064
998 ninehundredandninetyeight 25 21089
999 ninehundredandninetynine 24 21113
1000 onethousand 11 21124

1000까지는 and 를 추가로 붙여야 되는데, 100 으로 나누어 떨어지는 숫자마다는 and를 넣을 필요가 없습니다. 그래서 if문으로 100으로 나누어떨어지는지에 따라서 두가지로 나누어주면 됩니다.
그리고 맨마지막에 if문에 하나도 걸리지 않고 내려갔을때는 1000이니깐, "one"+"thousand"를 반환해주면 됩니다.

댓글

댓글 본문