This function computes the English string for any given integer supported by Clojure.
(int->str 110917) ; "one hundred and ten thousand nine hundred and seventeen"
How it works
Components in a number
The most important trick used is to first break the number down into its components (i.e. its millions, its thousands, hundreds and ones). We do this by successively dividing the number by the size of each component, starting with the largest supported component and carrying over the remainder. The function
solve-components takes care of this and outputs something of the form:
(solve-components 110927) ;[[:thousand 110] [:hundred 9] [:ten 2] [:one 7]]
Conversion to a string
Now we can write a function to name each component pair. The function
str-of-pair does this.
(str-of-pair [:thousand 110]) ; "one hundred and ten thousand"
For everything except the
:teens this is just a case of saying
(str (int->str value) " " (name component)). Note the recursion back into
int->str here in order to avoid saying "110 thousand". For the special cases, we use a lookup table.
Dealing with teens
There is a special case in English, where
[:ten 1] [:one 7] isn't "ten seven" but is rather "seventeen". We handle this by eliminating the
:ten and the
:one components and replacing them with a
:teen component (e.g.
[:teen 7]). The string conversion has a lookup table for
teenify function handle the substitution and is performed at the end of
Dealing with hundreds
In English, when a number is not a round hundred, we use the conjuction "and" before the remaining number. To handle this, we rebuild our list of components in reverse. If we see a
:hundred and we've already processed something before it, we inject the
[:str "and"] component, otherwise we just copy as-is. Remember we're processing in reverse to simplify the need to lookahead. The function
andify does this substitution and is performed at the end of
:str components as verbatim pieces of text.