Files
integreat/src/cljc/auto_ap/numeric.cljc
2018-05-17 19:37:50 -07:00

105 lines
3.4 KiB
Clojure

(ns auto-ap.numeric
(:require [clojure.string :as str]))
(def ^:private smalls ["zero"
"one"
"two"
"three"
"four"
"five"
"six"
"seven"
"eight"
"nine"
"ten"
"eleven"
"twelve"
"thirteen"
"fourteen"
"fifteen"
"sixteen"
"seventeen"
"eighteen"
"nineteen"])
(def ^:private tens ["twenty"
"thirty"
"forty"
"fifty"
"sixty"
"seventy"
"eighty"
"ninety"])
(def ^:private magnitudes ["thousand"
"million"
"billion"
"trillion"
"quadrillion"
"quintillion"
"sextillion"
"septillion"
"octillion"
"nonillion"
"decillion"
"undecillion"
"duodecillion"
"tredecillion"
"quattuordecillion"
"quindecillion"
"quinquadecillion"
"sexdecillion"
"sedecillion"
"septendecillion"
"octodecillion"
"novemdecillion"
"novendecillion"
"vigintillion"
#_"centillion"])
(defn words
[n]
{:pre [(not (neg? n))]}
(cond
(< n 20) (smalls n)
(< n 100) (let [pre (tens (- (quot n 10) 2)),
x (rem n 10)]
(if (zero? x) pre (str pre "-" (words x))))
(< n 1000) (let [hun (quot n 100),
x (rem n 100),
s (str (words hun) " hundred")]
(if (zero? x) s (str s " and " (words x))))
:else (loop [parts [] n n mag -1]
(if (zero? n)
(str/join " " parts)
(let [x (rem n 1000)
n (quot n 1000)
parts (if (zero? x)
parts
(let [s (words x)]
(cons
(if (neg? mag)
(if (< x 100)
(str "and " s)
s)
(str s " " (magnitudes mag)))
parts)))]
(recur parts n (inc mag)))))))
(defn num->words [num]
(let [total-cents (int (* 100 num))
dollar-num (int (quot total-cents 100))
cent-num (int (rem total-cents 100))
dollars (str (words dollar-num) " dollars")
cents (str (words cent-num) " cents")]
(cond
(and (> dollar-num 0) (> cent-num 0))
(str dollars " and " cents)
(> dollar-num 0)
dollars
:else
cents)))