把一千以內的數字轉爲英文的程序

發現一個網站,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))) 


 

發佈了109 篇原創文章 · 獲贊 14 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章