现在的位置: 首页 > 综合 > 正文

把一千以内的数字转为英文的程序

2019年03月11日 ⁄ 综合 ⁄ 共 1707字 ⁄ 字号 评论关闭

发现一个网站,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))) 

 

抱歉!评论已关闭.