Skip to content

Instantly share code, notes, and snippets.

@myguidingstar
Created March 28, 2020 19:15
Show Gist options
  • Save myguidingstar/d0c99c48cc4801eff6007b370818777a to your computer and use it in GitHub Desktop.
Save myguidingstar/d0c99c48cc4801eff6007b370818777a to your computer and use it in GitHub Desktop.
Number-> Vietnamese Words, ported to Ferret lang
(def str new-string)
(defmacro u8
[s]
(let [s# (into [] (.getBytes s))]
`(str (list ~@s#))))
(defn digit->words [c]
(cond
(= c \0) (u8 "không"),
(= c \1) (u8 "một"),
(= c \2) (u8 "hai"),
(= c \3) (u8 "ba"),
(= c \4) (u8 "bốn"),
(= c \5) (u8 "năm"),
(= c \6) (u8 "sáu"),
(= c \7) (u8 "bảy"),
(= c \8) (u8 "tám"),
(= c \9) (u8 "chín")))
(defn zero-or-one? [x]
(or (= x \0) (= x \1)))
(defn group-of-two->words [y z]
(if (= \1 y)
(let [tail (when-not (= \0 z)
(str " " (digit->words z)))]
(str (u8 "mười") tail))
(str (digit->words y) (u8 " mươi")
(when (not= \0 z)
(str " "
(cond
(and (= \1 z) (not (zero-or-one? y)))
(u8 "mốt")
(and (= \4 z) (not (zero-or-one? y)))
(u8 "tư")
(and (= \5 z) (not= \0 y))
(u8 "lăm")
:else
(digit->words z)))))))
(defn group-of-three->words [x y z]
(str
(digit->words x)
(if-not (= \0 x y z) (u8 " trăm"))
(cond
(= \0 y z)
""
(= \0 y)
(str (u8 " linh ") (digit->words z))
:else
(str " " (group-of-two->words y z)))))
(defn repeat [n x]
(repeatedly n (fn [] x)))
(defn interpose
[sep coll]
(reduce
(fn [acc x] (concat acc (list sep x)))
(list (first coll))
(rest coll)))
(defn link-groups [digits level paster separator]
(let [n-of-digits (count digits)
remainder (rem n-of-digits level)
digits-to-process (if (zero? remainder)
level
remainder)
repeated (dec (/ (- n-of-digits digits-to-process)
level))
head (take digits-to-process digits)
tail (drop digits-to-process digits)]
(str (number->words* head) " "
paster
(if (apply = (cons \0 tail))
(when (< 0 repeated)
(apply str " " (interpose " " (repeat repeated paster))))
(str separator " " (number->words* tail))))))
(defn number->words* [digits & [separator]]
(let [n-of-digits (count digits)]
(cond
(< 9 n-of-digits)
(link-groups digits 9 (u8 "tỷ") separator)
(< 6 n-of-digits)
(link-groups digits 6 (u8 "triệu") separator)
(< 3 n-of-digits)
(link-groups digits 3 (u8 "nghìn") separator)
(= 3 n-of-digits)
(apply group-of-three->words digits)
(= 2 n-of-digits)
(apply group-of-two->words digits)
(= 1 n-of-digits)
(apply digit->words digits))))
(let [[_program n sep] *command-line-args*]
(println (number->words* n sep)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment