2013年8月10日土曜日

[Project Euler] Problem 17 「数字の文字数」


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

数を英単語に置き換える手続きがあれば解けそうです. 空白やハイフンを数えないことになってるので, 英単語は文字列のリストとして表現します.

  1. 数を英単語に置き換える.
  2. 文字列を文字のリストに変換する.
  3. 文字の総数を求める.

手続きは次のようになります.

(require srfi/1)

(define (nbr-to-word n)
  (define (loop nbr)
    (cond ((= nbr 1) (list "one"))
          ((= nbr 2) (list "two"))
          ((= nbr 3) (list "three"))
          ((= nbr 4) (list "four"))
          ((= nbr 5) (list "five"))
          ((= nbr 6) (list "six"))
          ((= nbr 7) (list "seven"))
          ((= nbr 8) (list "eight"))
          ((= nbr 9) (list "nine"))
          ((= nbr 10) (list "ten"))
          ((= nbr 11) (list "eleven"))
          ((= nbr 12) (list "twelve"))
          ((= nbr 13) (list "thirteen"))
          ((= nbr 14) (list "fourteen"))
          ((= nbr 15) (list "fifteen"))
          ((= nbr 16) (list "sixteen"))
          ((= nbr 17) (list "seventeen"))
          ((= nbr 18) (list "eighteen"))
          ((= nbr 19) (list "nineteen"))
          ((= nbr 20) (list "twenty"))
          ((= nbr 30) (list "thirty"))
          ((= nbr 40) (list "forty"))
          ((= nbr 50) (list "fifty"))
          ((= nbr 60) (list "sixty"))
          ((= nbr 70) (list "seventy"))
          ((= nbr 80) (list "eighty"))
          ((= nbr 90) (list "ninety"))
          ((= nbr 1000) (list "one" "thousand"))
          ((and (>= nbr 100) (= (remainder nbr 100) 0)) 
           (append (loop (quotient nbr 100)) (list "hundred")))
          ((>= nbr 100) 
           (append (loop (quotient nbr 100)) 
                   (list "hundred" "and") 
                   (loop (remainder nbr 100))))
          ((>= nbr 21) 
           (append (loop (* (quotient nbr 10) 10)) 
                   (loop (remainder nbr 10))))))
  (loop n))
  

(define (word-length word)
  (length (apply append (map string->list word))))

計算してみます.

ようこそ DrRacket, バージョン 5.3.3 [3m].
言語: Pretty Big; memory limit: 512 MB.
> (map nbr-to-word (iota 150 1))
(("one")
 ("two")
 ("three")
 ("four")
 ("five")
 ("six")
 ("seven")
 ("eight")
 ("nine")
 ("ten")
 ("eleven")
 ("twelve")
 ("thirteen")
 ("fourteen")
 ("fifteen")
 ("sixteen")
 ("seventeen")
 ("eighteen")
 ("nineteen")
 ("twenty")
 ("twenty" "one")
 ("twenty" "two")

 ... 省略 ...

 ("ninety" "six")
 ("ninety" "seven")
 ("ninety" "eight")
 ("ninety" "nine")
 ("one" "hundred")
 ("one" "hundred" "and" "one")
 ("one" "hundred" "and" "two")
 ("one" "hundred" "and" "three")
 ("one" "hundred" "and" "four")

 ... 省略 ...

 ("one" "hundred" "and" "forty" "seven")
 ("one" "hundred" "and" "forty" "eight")
 ("one" "hundred" "and" "forty" "nine")
 ("one" "hundred" "and" "fifty"))
> (fold + 0 (map word-length (map nbr-to-word (iota 1000 1))))
21124
> 

0 件のコメント:

コメントを投稿