Skip to content

Instantly share code, notes, and snippets.

@kohyama
Created December 19, 2012 10:19
Show Gist options
  • Save kohyama/4335755 to your computer and use it in GitHub Desktop.
Save kohyama/4335755 to your computer and use it in GitHub Desktop.
Project Euler Problem 17
(require '[clojure.test :refer (is)])
(defn in-words
"Represents the given number in English words without spaces nor hyphens.
This works with a number in the range from 1 to 1000"
[n]
(cond
(< n 20)
(["" "one" "two" "three" "four" "five" "six" "seven" "eight"
"nine" "ten" "eleven" "twelve" "thirteen" "fourteen"
"fifteen" "sixteen" "seventeen" "eighteen" "nineteen"] n)
(< n 100)
(str
(["twenty" "thirty" "forty" "fifty" "sixty" "seventy"
"eighty" "ninety"] (- (quot n 10) 2))
(in-words (mod n 10)))
(< n 1000)
(let [nmod100 (mod n 100)]
(str
(in-words (quot n 100))
"hundred"
(if (zero? nmod100) ""
(str "and" (in-words nmod100)))))
(= n 1000) "onethousand"))
(is (= (in-words 18) "eighteen"))
(is (= (in-words 746) "sevenhundredandfortysix"))
(defn pep017
"Counts letters of words representing numbers from 1 to the given number"
([n] (apply + (map (comp count in-words) (range 1 (inc n)))))
([] (pep017 1000)))
(is (= (pep017 5) 19))
(pep017)
@plaster
Copy link

plaster commented Jan 3, 2013

私も @kohyama さんとほとんど同じ解き方になりました。20未満が特別扱いになること、かつ mod 10 や quot 100 の部品としても使えるのがいいですよね。
@tnodaさん紹介のICU4Jは、文字の扱い周りで名前だけ聞いたことがあった気がします。こんなことまでやってくれるのはびっくりです。

@emanon001
Copy link

僕も @plaster さんと同様に、@kohyama さんとほとんど同じ解き方でした。ローマ数字や漢数字と比べると、特別扱いする数が多いので、少し戸惑いました。

ベクタやマップ、キーワードが関数としても使用できることについては、Clojure を学び始めた当初、相当な違和感と気持ち悪さを感じていましたが、今ではすっかり便利な機能だと感じるようになりました。

あと、解答には直接関係ないのですが、cond のインデントが気に入りました。

(cond
  (test-a)
    (expr-a)
  (test-b)
    (expr-b))

VimClojure だと testexpr 間でインデントが変わらないため、手動でインデントを修正する必要がありますが……


おお、ICU4J すごい。毎度のことですが、@tnoda さんが Clojure から Java の既存ライブラリが使用できることの有用性を示してくれているのはとても有り難いです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment