오일러프로젝트017

오일러프로젝트 017

숫자값을 영어단어 표기로 바꾸는 부분은 여러가지로 귀찮은 분기처리가 많을 수 있지만, 이를 간략화하기위한 아이디어를 생각해보자.

  1. 1~19 사이의 값은 각각 고유한 단어로 되어 있다.
  2. 20~99 사이의 값은 10자리를 나타내는 단어 + 1자리를 나타내는 단어로 구성된다.
  3. 100~999 사이의 값은 백단위값 + [and + 99이하의 값]이 된다.

따라서 각 단위의 단어들을 튜플에 저장해놓고, 단위값으로 나눈 몫을 인덱스로 사용하는 (그리고 최종 나머지는 1~19사이의 단어를 쓰도록) 할 수 있겠다. 이렇게 하면 실제 변환해야 하는 값을 인덱스로 이용하기만 하면 되기 때문에 코드가 좀 더 간단해질 수 있다.

아래는 파이썬 풀이.

words1000 = 'thousand'
words100 = 'hundred'
words20 = ('', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty',
           'seventy', 'eighty', 'ninety')
words1 = ('', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
          'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
          'sixteen', 'seventeen', 'eighteen', 'nineteen')

def words(n):
    s = ""
    if n == 1000:
        s += words1[n // 1000] + words1000
        n = n % 1000
    if n > 99:
        s += words1[n // 100] + words100
        n = n % 100
        if n > 0:
            s += "and"
    if n >= 20:
        s += words20[n // 10]
        n = n % 10
    s += words1[n]
    return s

def p17():
    print(sum((len(words(n)) for n in range(1, 1001))))

%time p17()

# 21124
# Wall time: 3 ms

아래는 숫자를 단어로 변환하는 words 함수를 재귀적으로 사용하게끔하여 조금 더 짧게 쓴 버전.

words20 = ('', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty',
           'seventy', 'eighty', 'ninety')
words1 = ('', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
          'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
          'sixteen', 'seventeen', 'eighteen', 'nineteen')

def words(n):
    if n == 1000:
        return "onethousand"
    if n > 99:
        return words1[n // 100] + "hundred" + ("" if n % 100 == 0 else "and" + words(n % 100))
    if n >= 20:
        return words20[n // 10] + words(n % 10)
    return words1[n % 20]

def p17():
    print(sum(len(words(n)) for n in range(1, 1001)))


%time p17()
  • openingnow

    혹시 if n == 1000 이 부분은 오타인가요?

    • ? 오타없이 실행되는 코드입니다만?