Problem17

30分プログラム、その283。Problem17 via Project Euler

1 から 5 までの数字を英単語で書けば one, two, three, four, five であり、全部で 3 + 3 + 4 + 4 + 5 = 19 の文字が使われている。
では 1 から 1000 (one thousand) までの数字をすべて英単語で書けば、全部で何文字になるか。
注: 空白文字やハイフンを数えないこと。例えば、342 (three hundred and forty-two) は 23 文字、115 (one hundred and fifteen) は20文字と数える。なお、"and" を使用するのは英国の慣習。

地味に1から順に英語に変換して、文字列の長さを計算して、和を求めた。andが実に憎たらしい。

使い方

$ time python problem17.py
21124
python problem17.py  0.15s user 0.06s system 96% cpu 0.216 total

ソースコード

#! /usr/bin/python
# -*- mode:python; coding:utf-8 -*-
#
# problem17.py -
#
# Copyright(C) 2008 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2008/04/09 15:56:55
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#

Digit = ['one','two','three','four','five','six','seven','egiht','nine']
Special = {
    10 : 'ten',
    11 : 'eleven',
    12 : 'twelve',
    13 : 'thirteen',
    14 : 'fourteen',
    15 : 'fifteen',
    16 : 'sixteen',
    17 : 'seventeen',
    18 : 'eighteen',
    19 : 'nineteen',
    }

X10 = {
    2: 'twenty',
    3: 'thirty',
    4: 'forty',
    5: 'fifty',
    6: 'sixty',
    7: 'seventy',
    8: 'eighty',
    9: 'ninety'
    }

def english_num(n):
    """
>>> english_num(10)
['ten']
>>> english_num(19)
['nineteen']
>>> english_num(35)
['thirty', 'five']
>>> english_num(342)
['three', 'hundred', 'and', 'forty', 'two']
>>> english_num(1000)
['one', 'thousand']
    """
    if n in Special:
        return [Special[n]]
    elif n == 0:
        return []
    elif n < 10:
        return [Digit[n-1]]
    elif n < 100:
        q = n / 10
        r = n % 10
        return [ X10[q] ] + english_num(r)
    elif n < 1000:
        q = n / 100
        r = n % 100

        rest = english_num(r)

        lst = english_num(q)
        lst.append('hundred')
        if rest != []:
            lst.append('and')
        return lst+rest
    else:
        q = n / 1000
        r = n % 1000
        return english_num(q) + ['thousand'] + english_num(r)

def _test():
    import doctest
    doctest.testmod()

if __name__ == "__main__":
    _test()
    length = 0
    for n in xrange(1,1001):
        length += sum(map(len,english_num(n)))
    print length