1 ! Copyright (c) 2007 Aaron Schaefer.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: combinators.lib kernel math math.functions math.parser namespaces
4 sequences splitting grouping sequences.lib
5 combinators.short-circuit ;
10 : small-numbers ( n -- str )
11 { "Zero" "One" "Two" "Three" "Four" "Five" "Six" "Seven" "Eight" "Nine"
12 "Ten" "Eleven" "Twelve" "Thirteen" "Fourteen" "Fifteen" "Sixteen"
13 "Seventeen" "Eighteen" "Nineteen" } nth ;
16 { f f "Twenty" "Thirty" "Forty" "Fifty" "Sixty" "Seventy" "Eighty" "Ninety" } nth ;
18 : scale-numbers ( n -- str ) ! up to 10^99
19 { f "Thousand" "Million" "Billion" "Trillion" "Quadrillion" "Quintillion"
20 "Sextillion" "Septillion" "Octillion" "Nonillion" "Decillion" "Undecillion"
21 "Duodecillion" "Tredecillion" "Quattuordecillion" "Quindecillion"
22 "Sexdecillion" "Septendecillion" "Octodecillion" "Novemdecillion"
23 "Vigintillion" "Unvigintillion" "Duovigintillion" "Trevigintillion"
24 "Quattuorvigintillion" "Quinvigintillion" "Sexvigintillion"
25 "Septvigintillion" "Octovigintillion" "Novemvigintillion" "Trigintillion"
26 "Untrigintillion" "Duotrigintillion" } nth ;
29 : set-conjunction ( seq -- )
30 first { [ dup 100 < ] [ dup 0 > ] } 0&& and-needed? set drop ;
32 : negative-text ( n -- str )
33 0 < "Negative " "" ? ;
35 : 3digit-groups ( n -- seq )
36 number>string <reversed> 3 <groups>
37 [ reverse string>number ] map ;
39 : hundreds-place ( n -- str )
40 100 /mod swap dup zero? [
43 small-numbers " Hundred" append
44 swap zero? [ " and " append ] unless
47 : tens-place ( n -- str )
50 dup zero? [ drop ] [ "-" swap small-numbers 3append ] if
52 dup zero? [ drop "" ] [ small-numbers ] if
55 : 3digits>text ( n -- str )
56 dup hundreds-place swap tens-place append ;
58 : text-with-scale ( index seq -- str )
59 dupd nth 3digits>text swap
60 scale-numbers dup empty? [
66 : append-with-conjunction ( str1 str2 -- newstr )
70 and-needed? get " and " ", " ? rot 3append
74 : (recombine) ( str index seq -- newstr seq )
78 [ text-with-scale ] keep
79 -rot append-with-conjunction swap
82 : recombine ( seq -- str )
86 dup set-conjunction "" swap
87 dup length [ swap (recombine) ] each drop
90 : (number>text) ( n -- str )
91 dup negative-text swap abs 3digit-groups recombine append ;
95 : number>text ( n -- str )
99 [ (number>text) ] with-scope