发现一个网站,Projecteuler.net,上面可以做题。
其中第17道题是关于把1至一千的的数字转成英文单词的。写了一个程序可以完成这个功能,应该容易扩展为任意大的数字。程序写得挺复杂,肯定有简便方法。故意用不熟悉的Clojure语言写的,据说用函数式编程语言写程序想的时间比写的时间多,确实如此,应该是有效防止老年痴呆的方法。英文数字通常3个一组用逗号分隔,是有道理的,确实每三个是一个轮回。
;problem 17; (def max-digit-num 4) (def dict { 0 "" 1 "one" 2 "two" 3 "three" 4 "four" 5 "five" 6 "six" 7 "seven" 8 "eight" 9 "nine" 10 "ten" 11 "eleven" 12 "twelve" 13 "thirteen" 14 "fourteen" 15 "fifteen" 16 "sixteen" 17 "seventeen" 18 "eighteen" 19 "nineteen" 20 "twenty" 30 "thirty" 40 "forty" 50 "fifty" 60 "sixty" 70 "seventy" 80 "eighty" 90 "ninety" }) (defn digit-seq [num] (if (zero? num) [] (cons (rem num 10) (digit-seq (quot num 10))))) (defn digit-seq-with-trailing-0 [num, len] (let [ds (digit-seq num), cur-len (count ds) ] (if (>= cur-len len) ds (concat ds (repeat (- len cur-len) 0)) ) ) ) (defn digit-seq-with-index [num] (reverse (map-indexed #( vector %1 %2 ) (digit-seq-with-trailing-0 num max-digit-num) ))) (defn sum-digit-seq-with-index [s] (reduce #(+ (* %1 10) (second %2)) 0 s)) (defn digit2words [index,d, remain-sum] (cond (= 0 d) "" (= 0 index) (dict d) (= 1 index) (if (= d 1) (dict (+ (* 10 d) remain-sum)) (dict (* 10 d))) (= 2 index) (if (= remain-sum 0) (apply str (interpose " " [ (dict d) "hundred" ])) (apply str (interpose " " [ (dict d) "hundred and" ]))) (= 3 index) (apply str (interpose " " [ (dict d) "thousand"])) :else (dict d) ) ) (defn num2words [num] (let [digits (digit-seq-with-index num)] (loop [ds digits, result ""] (if (empty? ds) result (let [ [idx,digit] (first ds), remain-seq (rest ds), remain-num (sum-digit-seq-with-index remain-seq), curr-result (digit2words idx digit remain-num), former-plus-curr (apply str (interpose " " [result curr-result])) ] (if (and (= idx 1) (= digit 1)) former-plus-curr (recur remain-seq former-plus-curr)))) ) ) ) (defn count-non-blank-char [s] (reduce #(+ %1 ( if (= %2 \space) 0 1)) 0 s)) (print (reduce + (map (comp count-non-blank-char num2words) (range 1 1001))) ) (print (map num2words (range 1 1001)))