Project Euler #017 – 数字を英単語で

In: Project Euler

11 1月 2010

Project EulerをClojureでおさらいシリーズ。
Problem 17

オリジナルはこちら

日本語訳:

1から5までを英単語で表すと one, two, three, four, five となり、 文字数の合計は 3 + 3 + 5 + 4 + 4 = 19 となる。

1から1000までを英単語で表すと文字数の合計はいくらになるか。

注意:スペースとハイフンはカウントしない。例えば 342 (three hundred and forty-two) は23文字となり、115 (one hundred and fifteen) は20文字となる。 英単語での表記の”and”の使い方はイギリス英語のそれに準じることとする。

fourteen と forty の綴りには注意。あとはそんなに難しくない。

以前Rubyで解いたもの:

#!/usr/bin/env ruby
 
One_to_Nine = %W(#{} one two three four five six seven eight nine)
Teen = %W(#{} #{} #{} thir four fif six seven eigh nine)
Ty = %W(#{} #{} twen thir for fif six seven eigh nine)
Ten_to_Twelve = %w(ten eleven twelve)
Handred = " handred"
Thousand = " thousand"
 
def spell(num)
  r = []
  d = []
  (0..3).each do |digit|
    d[digit] = num % 10**(digit+1) / 10**digit
  end
 
  r << One_to_Nine[d[3]] + Thousand if d[3] > 0
  r << One_to_Nine[d[2]] + Handred  if d[2] > 0
  r << "and" if (d[3] + d[2]) * (d[1] + d[0]) > 0
  if d[1] == 1
    r << Teen[d[0]] + "teen" if d[0] > 2
    r << Ten_to_Twelve[d[0]] if d[0] <= 2
  else
    r << Ty[d[1]] + "ty" if d[1] > 1
    r << One_to_Nine[d[0]] if d[0] > 0
  end
 r.join(" ").sub("ty ", "ty-")
end
 
def count_letter(num)
  spell(num).tr(" -", "").size
end
 
p 1.upto(1000).inject(0){|s,n| s + count_letter(n)}

効率化しようとしてムダに力が入っているな・・。

今回はClojureで:

(ns euler.p017)
 
(def one-to-nineteen
     ["" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"
      "ten" "eleven" "twelve" "thirteen" "fourteen" "fifteen"
      "sixteen" "seventeen" "eighteen" "nineteen"])
 
(def twenty-to-ninety
     ["twenty" "thirty" "forty" "fifty" "sixty" "seventy" "eighty" "ninety"])
 
(defn spell-num
  "Return number as english-word."
  ([n] (spell-num n ""))
  ([n preword]
     (cond
       (= n 0) ""
       (< n 20) (str preword (nth one-to-nineteen n))
       (< n 100) (str preword
		      (nth twenty-to-ninety (/ (- n 20) 10))
		      (spell-num (rem n 10) "-"))
       (< n 1000) (str preword
		       (spell-num (/ n 100)) " hundred"
		       (spell-num (rem n 100) " and "))
       (< n 10000) (str (spell-num (/ n 1000)) " thousand"
			(spell-num (rem n 1000) " ")))))
 
(defn remove-spaces-and-hyphens
  [word]
  (apply str (re-seq #"\w+" word)))
 
(println "Answer : "
	 (count
	  (apply str
		 (map #(remove-spaces-and-hyphens (spell-num %))
		      (range 1 1001)))))

再帰を中心に考えてみた。

spell-num の中に繰り返しパターンがあるのがちょっと気になる。うーむ。

blog comments powered by Disqus
Get Adobe Flash playerPlugin by wpburn.com wordpress themes

About this blog

私 manjilab のポータル的サイトになっております。日々気付いたこと、考えたこと、発表したいものを載せていきます。

Photostream

    Lisp indent 考察Lisp indent 考察Lisp indent 考察Lisp indent 考察Lisp indent 考察Tips to use Clojure(Lisp) with TextMateTips to use Clojure(Lisp) with TextMateTips to use Clojure(Lisp) with TextMate