yaterbilang/
lib.rs

1mod divider;
2
3/// Converts u64 number to said Indonesian
4///
5/// Examples:
6///
7/// ```
8/// use yaterbilang as terbilang;
9///
10/// assert_eq!(terbilang::from(0), "nol");
11/// assert_eq!(terbilang::from(11), "sebelas");
12/// assert_eq!(terbilang::from(32), "tiga puluh dua");
13/// assert_eq!(terbilang::from(998), "sembilan ratus sembilan puluh delapan");
14/// ```
15///
16pub fn from(number: u64) -> String {
17    if number == 0 {
18        return String::from("nol");
19    } else if number < 10 {
20        return solve_basic_number(number)
21    } else if number < 100 {
22        return solve_tens(number)
23    } else if number < 1_000 {
24        return solve_hundreds(number)
25    } else if number < 10_000 {
26        return solve_thousands(number)
27    } else if number < 100_000 {
28        return solve_tens_of_thousands(number)
29    } else if number < 1_000_000 {
30        return solve_hundreds_of_thousands(number)
31    } else if number < 10_000_000 {
32        return solve_millions(number)
33    } else if number < 100_000_000 {
34        return solve_tens_of_millions(number)
35    } else if number < 1_000_000_000 {
36        return solve_hundreds_of_millions(number)
37    } else if number < 10_000_000_000 {
38        return solve_billions(number)
39    } else if number < 100_000_000_000 {
40        return solve_tens_of_billions(number)
41    } else if number< 1_000_000_000_000 {
42        return solve_hundreds_of_billions(number)
43    }
44    todo!("The number is too high and not supported at the moment");
45}
46
47/// Joins list of string to a single string
48fn join_string(list: Vec<String>) -> String {
49    let joined_string = list.join(" ");
50    let trimmed_string = joined_string.trim();
51    trimmed_string.to_string()
52}
53
54/// Solve 1 - 9
55fn solve_basic_number(number: u64) -> String {
56    match number {
57        0 => String::from(""),
58        1 => String::from("satu"),
59        2 => String::from("dua"),
60        3 => String::from("tiga"),
61        4 => String::from("empat"),
62        5 => String::from("lima"),
63        6 => String::from("enam"),
64        7 => String::from("tujuh"),
65        8 => String::from("delapan"),
66        9 => String::from("sembilan"),
67        _ => panic!("Basic number exceeded 9")
68    }
69}
70
71/// Solve 12 - 99
72fn solve_tens(number: u64) -> String {
73    let divide_result = divider::DivideResult::from(number, 10);
74    if divide_result.head == 1 {
75        if divide_result.remainder == 0 {
76            String::from("sepuluh")
77        } else if divide_result.remainder == 1 {
78            String::from("sebelas")
79        } else {
80            format!("{} belas", solve_basic_number(divide_result.remainder))
81        }
82    } else {
83        if divide_result.head == 0 {
84            solve_basic_number(divide_result.remainder)
85        } else {
86            join_string(vec![
87                format!("{} puluh", solve_basic_number(divide_result.head)),
88                solve_basic_number(divide_result.remainder),
89            ])
90        }
91    }
92}
93
94/// Solve 100 - 999
95fn solve_hundreds(number: u64) -> String {
96    let divide_result = divider::DivideResult::from(number, 100);
97    if divide_result.head == 0 {
98        solve_tens(divide_result.remainder)
99    } else if divide_result.head == 1 {
100        join_string(vec![
101            String::from("seratus"),
102            solve_tens(divide_result.remainder),
103        ])
104    } else {
105        join_string(vec![
106            format!("{} ratus", solve_basic_number(divide_result.head)),
107            solve_tens(divide_result.remainder),
108        ])
109    }
110}
111
112/// Solve 1.000 - 9.999
113fn solve_thousands(number: u64) -> String {
114    let divide_result = divider::DivideResult::from(number, 1_000);
115    if divide_result.head == 0 {
116        solve_hundreds(divide_result.remainder)
117    } else if divide_result.head == 1 {
118        join_string(vec![
119            String::from("seribu"),
120            solve_hundreds(divide_result.remainder),
121        ])
122    } else {
123        join_string(vec![
124            format!("{} ribu", solve_basic_number(divide_result.head)),
125            solve_hundreds(divide_result.remainder),
126        ])
127    }
128}
129
130/// Solve 10.000 - 99.999
131fn solve_tens_of_thousands(number: u64) -> String {
132    let divide_result = divider::DivideResult::from(number, 1_000);
133    if divide_result.head < 10 {
134        solve_thousands(number)
135    } else {
136        join_string(vec![
137            format!("{} ribu", solve_tens(divide_result.head)),
138            solve_thousands(divide_result.remainder),
139        ])
140    }
141}
142
143/// Solve 100.000 - 999.999
144fn solve_hundreds_of_thousands(number: u64) -> String {
145    let divide_result = divider::DivideResult::from(number, 1_000);
146    if divide_result.head < 100 {
147        solve_thousands(number)
148    } else {
149        join_string(vec![
150            format!("{} ribu", solve_hundreds(divide_result.head)),
151            solve_thousands(divide_result.remainder),
152        ])
153    }
154}
155
156/// Solve 1.000.000 - 9.999.999
157fn solve_millions(number: u64) -> String {
158    let divide_result = divider::DivideResult::from(number, 1_000_000);
159    if divide_result.head == 0 {
160        solve_hundreds_of_thousands(number)
161    } else {
162        join_string(vec![
163            format!("{} juta", solve_basic_number(divide_result.head)),
164            solve_hundreds_of_thousands(divide_result.remainder),
165        ])
166    }
167}
168
169/// Solve 10.000.000 - 99.999.999
170fn solve_tens_of_millions(number: u64) -> String {
171    let divide_result = divider::DivideResult::from(number, 1_000_000);
172    if divide_result.head < 10 {
173        solve_millions(number)
174    } else {
175        join_string(vec![
176            format!("{} juta", solve_tens(divide_result.head)),
177            solve_hundreds_of_thousands(divide_result.remainder),
178        ])
179    }
180}
181
182/// Solve 100.000.000 - 999.999.999
183fn solve_hundreds_of_millions(number: u64) -> String {
184    let divide_result = divider::DivideResult::from(number, 1_000_000);
185    if divide_result.head < 100 {
186        solve_millions(number)
187    } else {
188        join_string(vec![
189            format!("{} juta", solve_hundreds(divide_result.head)),
190            solve_hundreds_of_thousands(divide_result.remainder),
191        ])
192    }
193}
194
195/// Solve 1.000.000.000 - 9.999.999.999
196fn solve_billions(number: u64) -> String {
197    let divide_result = divider::DivideResult::from(number, 1_000_000_000);
198    if divide_result.head == 0 {
199        solve_hundreds_of_millions(number)
200    } else {
201        join_string(vec![
202            format!("{} triliun", solve_basic_number(divide_result.head)),
203            solve_hundreds_of_millions(divide_result.remainder),
204        ])
205    }
206}
207
208/// Solve 10.000.000.000 - 99.999.999.999
209fn solve_tens_of_billions(number: u64) -> String {
210    let divide_result = divider::DivideResult::from(number, 1_000_000_000);
211    if divide_result.head < 10 {
212        solve_billions(number)
213    } else {
214        join_string(vec![
215            format!("{} triliun", solve_tens(divide_result.head)),
216            solve_hundreds_of_millions(divide_result.remainder),
217        ])
218    }
219}
220
221/// Solve 100.000.000.000 - 999.999.999.999
222fn solve_hundreds_of_billions(number: u64) -> String {
223    let divide_result = divider::DivideResult::from(number, 1_000_000_000);
224    if divide_result.head < 100 {
225        solve_billions(number)
226    } else {
227        join_string(vec![
228            format!("{} triliun", solve_hundreds(divide_result.head)),
229            solve_hundreds_of_millions(divide_result.remainder),
230        ])
231    }
232}
233
234#[cfg(test)]
235mod basic_number_tests {
236    use super::*;
237
238    #[test]
239    fn satu() {
240        assert_eq!(solve_basic_number(1), String::from("satu"));
241    }
242
243    #[test]
244    fn dua() {
245        assert_eq!(solve_basic_number(2), String::from("dua"));
246    }
247
248    #[test]
249    fn tiga() {
250        assert_eq!(solve_basic_number(3), String::from("tiga"));
251    }
252
253    #[test]
254    fn empat() {
255        assert_eq!(solve_basic_number(4), String::from("empat"));
256    }
257
258    #[test]
259    fn lima() {
260        assert_eq!(solve_basic_number(5), String::from("lima"));
261    }
262
263    #[test]
264    fn enam() {
265        assert_eq!(solve_basic_number(6), String::from("enam"));
266    }
267
268    #[test]
269    fn tujuh() {
270        assert_eq!(solve_basic_number(7), String::from("tujuh"));
271    }
272
273    #[test]
274    fn delapan() {
275        assert_eq!(solve_basic_number(8), String::from("delapan"));
276    }
277
278    #[test]
279    fn sembilan() {
280        assert_eq!(solve_basic_number(9), String::from("sembilan"));
281    }
282}
283
284#[cfg(test)]
285mod teens_test {
286    use super::*;
287
288    #[test]
289    fn dua_belas() {
290        assert_eq!(solve_tens(12), String::from("dua belas"));
291    }
292
293    #[test]
294    fn sembilan_belas() {
295        assert_eq!(solve_tens(19), String::from("sembilan belas"));
296    }
297}