forked from adamdruppe/arsd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
english.d
148 lines (135 loc) · 3.32 KB
/
english.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/// A few helper functions for manipulating English words. Extremely basic.
module arsd.english;
/++
Given a non-one `count` argument, will attempt to return the plural version of `word`. Only handles basic cases. If count is one, simply returns the word.
I originally wrote this for cases like `You have {n} {messages|plural(n)}` in web templates.
+/
string plural(int count, string word, string pluralWord = null) {
if(count == 1 || word.length == 0)
return word; // it isn't actually plural
if(pluralWord !is null)
return pluralWord;
switch(word[$ - 1]) {
case 's':
case 'a', 'e', 'i', 'o', 'u':
return word ~ "es";
case 'f':
return word[0 .. $-1] ~ "ves";
case 'y':
return word[0 .. $-1] ~ "ies";
default:
return word ~ "s";
}
}
/// Given an integer, tries to write out the long form number. For example, -5 becomes "negative five".
string numberToEnglish(long number) {
string word;
if(number == 0)
return "zero";
if(number < 0) {
word = "negative";
number = -number;
}
while(number) {
if(number < 100) {
if(number < singleWords.length) {
word ~= singleWords[cast(int) number];
break;
} else {
auto tens = number / 10;
word ~= tensPlaceWords[cast(int) tens];
number = number % 10;
if(number)
word ~= "-";
}
} else if(number < 1000) {
auto hundreds = number / 100;
word ~= onesPlaceWords[cast(int) hundreds] ~ " hundred";
number = number % 100;
if(number)
word ~= " and ";
} else if(number < 1000000) {
auto thousands = number / 1000;
word ~= numberToEnglish(thousands) ~ " thousand";
number = number % 1000;
if(number)
word ~= ", ";
} else if(number < 1_000_000_000) {
auto millions = number / 1000000;
word ~= numberToEnglish(millions) ~ " million";
number = number % 1000000;
if(number)
word ~= ", ";
} else if(number < 1_000_000_000_000) {
auto n = number / 1000000000;
word ~= numberToEnglish(n) ~ " billion";
number = number % 1000000000;
if(number)
word ~= ", ";
} else if(number < 1_000_000_000_000_000) {
auto n = number / 1000000000000;
word ~= numberToEnglish(n) ~ " trillion";
number = number % 1000000000000;
if(number)
word ~= ", ";
} else {
import std.conv;
return to!string(number);
}
}
return word;
}
unittest {
assert(numberToEnglish(1) == "one");
assert(numberToEnglish(5) == "five");
assert(numberToEnglish(13) == "thirteen");
assert(numberToEnglish(54) == "fifty-four");
assert(numberToEnglish(178) == "one hundred and seventy-eight");
assert(numberToEnglish(592) == "five hundred and ninety-two");
assert(numberToEnglish(1234) == "one thousand, two hundred and thirty-four");
assert(numberToEnglish(10234) == "ten thousand, two hundred and thirty-four");
assert(numberToEnglish(105234) == "one hundred and five thousand, two hundred and thirty-four");
}
enum onesPlaceWords = [
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
];
enum singleWords = onesPlaceWords ~ [
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
];
enum tensPlaceWords = [
null,
"ten",
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety",
];
/*
void main() {
import std.stdio;
foreach(i; 3433000 ..3433325)
writeln(numberToEnglish(i));
}
*/