1struct ValueLabel {
2 value: i64,
3 label: &'static str,
4}
5
6static DENOMINASI: [ValueLabel; 6] = [
8 ValueLabel {
9 value: 1_000_000_000_000,
10 label: "triliun",
11 },
12 ValueLabel {
13 value: 1_000_000_000,
14 label: "milyar",
15 },
16 ValueLabel {
17 value: 1_000_000,
18 label: "juta",
19 },
20 ValueLabel {
21 value: 1_000,
22 label: "ribu",
23 },
24 ValueLabel {
25 value: 100,
26 label: "ratus",
27 },
28 ValueLabel {
29 value: 10,
30 label: "puluh",
31 },
32];
33
34static SATUAN: [ValueLabel; 12] = [
35 ValueLabel {
36 value: 0,
37 label: "nol",
38 },
39 ValueLabel {
40 value: 1,
41 label: "satu",
42 },
43 ValueLabel {
44 value: 2,
45 label: "dua",
46 },
47 ValueLabel {
48 value: 3,
49 label: "tiga",
50 },
51 ValueLabel {
52 value: 4,
53 label: "empat",
54 },
55 ValueLabel {
56 value: 5,
57 label: "lima",
58 },
59 ValueLabel {
60 value: 6,
61 label: "enam",
62 },
63 ValueLabel {
64 value: 7,
65 label: "tujuh",
66 },
67 ValueLabel {
68 value: 8,
69 label: "delapan",
70 },
71 ValueLabel {
72 value: 9,
73 label: "sembilan",
74 },
75 ValueLabel {
76 value: 10,
77 label: "sepuluh",
78 },
79 ValueLabel {
80 value: 11,
81 label: "sebelas",
82 },
83];
84
85fn satuan(number: i64) -> String {
86 if let Some(n) = SATUAN.iter().find(|x| x.value == number) {
87 String::from(n.label)
88 } else {
89 "".to_string() }
91}
92
93fn belasan(number: i64) -> String {
94 format!("{} belas", terbilang_helper(number % 10))
95}
96
97fn other(number: i64) -> String {
98 if let Some(denom) = DENOMINASI.iter().find(|x| number >= x.value) {
99 let s = format!(
100 "{} {}",
101 terbilang_helper(number / denom.value),
102 denom.label
103 );
104 let s = if number % denom.value == 0 {
105 s
106 } else {
107 format!("{} {}", s, terbilang_helper(number % denom.value))
108 };
109 s.replace("satu ratus", "seratus")
110 .replace("satu ribu", "seribu")
111 } else {
112 "".to_string() }
114}
115
116fn terbilang_helper(number: i64) -> String {
117 match number {
118 0..=11 => satuan(number),
119 12..=19 => belasan(number),
120 _ => other(number),
121 }
122}
123
124pub fn terbilang(number: i64) -> String {
133 let s = terbilang_helper(number.abs());
134 if number < 0 {
135 format!("negatif {}", s)
136 } else {
137 s
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn terbilang_it_works() {
147 let tests = [
148 (-1_123_456_789_123, "negatif satu triliun seratus dua puluh tiga milyar empat ratus lima puluh enam juta tujuh ratus delapan puluh sembilan ribu seratus dua puluh tiga"),
149 (-1_000, "negatif seribu"),
150 (0, "nol"),
151 (1, "satu"),
152 (2, "dua"),
153 (3, "tiga"),
154 (4, "empat"),
155 (5, "lima"),
156 (6, "enam"),
157 (7, "tujuh"),
158 (8, "delapan"),
159 (9, "sembilan"),
160 (10, "sepuluh"),
161 (11, "sebelas"),
162 (12, "dua belas"),
163 (13, "tiga belas"),
164 (14, "empat belas"),
165 (15, "lima belas"),
166 (16, "enam belas"),
167 (17, "tujuh belas"),
168 (18, "delapan belas"),
169 (19, "sembilan belas"),
170 (20, "dua puluh"),
171 (29, "dua puluh sembilan"),
172 (99, "sembilan puluh sembilan"),
173 (100, "seratus"),
174 (110, "seratus sepuluh"),
175 (111, "seratus sebelas"),
176 (119, "seratus sembilan belas"),
177 (220, "dua ratus dua puluh"),
178 (1000, "seribu"),
179 (1019, "seribu sembilan belas"),
180 (1119, "seribu seratus sembilan belas"),
181 (2210, "dua ribu dua ratus sepuluh"),
182 (2220, "dua ribu dua ratus dua puluh"),
183 (10000, "sepuluh ribu"),
184 (12220, "dua belas ribu dua ratus dua puluh"),
185 (22220, "dua puluh dua ribu dua ratus dua puluh"),
186 (222220, "dua ratus dua puluh dua ribu dua ratus dua puluh"),
187 (2222220, "dua juta dua ratus dua puluh dua ribu dua ratus dua puluh"),
188 (22222220, "dua puluh dua juta dua ratus dua puluh dua ribu dua ratus dua puluh"),
189 (222222220, "dua ratus dua puluh dua juta dua ratus dua puluh dua ribu dua ratus dua puluh"),
190 (987654321, "sembilan ratus delapan puluh tujuh juta enam ratus lima puluh empat ribu tiga ratus dua puluh satu"),
191 (1234567890, "satu milyar dua ratus tiga puluh empat juta lima ratus enam puluh tujuh ribu delapan ratus sembilan puluh"),
192 (2222222220, "dua milyar dua ratus dua puluh dua juta dua ratus dua puluh dua ribu dua ratus dua puluh"),
193 (1231234567890, "satu triliun dua ratus tiga puluh satu milyar dua ratus tiga puluh empat juta lima ratus enam puluh tujuh ribu delapan ratus sembilan puluh"),
194 (451231234567890, "empat ratus lima puluh satu triliun dua ratus tiga puluh satu milyar dua ratus tiga puluh empat juta lima ratus enam puluh tujuh ribu delapan ratus sembilan puluh"),
195 (4561231234567890, "empat ribu lima ratus enam puluh satu triliun dua ratus tiga puluh satu milyar dua ratus tiga puluh empat juta lima ratus enam puluh tujuh ribu delapan ratus sembilan puluh"),
196 ];
197
198 for test in tests.iter() {
199 assert_eq!(terbilang(test.0), String::from(test.1));
200 }
201 }
202}