Created
March 28, 2020 19:15
-
-
Save myguidingstar/d0c99c48cc4801eff6007b370818777a to your computer and use it in GitHub Desktop.
Number-> Vietnamese Words, ported to Ferret lang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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