-
Notifications
You must be signed in to change notification settings - Fork 6
/
converters.go
269 lines (233 loc) · 5.98 KB
/
converters.go
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
package aznum2words
import (
"strconv"
"strings"
)
// Extract the sign mark('-') and convert into word
// getSignSymbolAsWord("-123") -> "mənfi"
// getSignSymbolAsWord("123") -> ""
func getSignSymbolAsWord(str string) (string, error) {
if str == "" {
return "", ErrInvalidArgument
}
var sign string
if len(str) > 1 && str[0:1] == "-" {
sign = NegativeAsWord
}
return sign, nil
}
// Remove the sign mark:('-' or '+') from str
// removeSignMarkIfExists("-123") -> "123"
// removeSignMarkIfExists("+123") -> "123"
// removeSignMarkIfExists("123") -> "123"
func removeSignMarkIfExists(str string) string {
if len(str) > 1 && (str[0:1] == "-" || str[0:1] == "+") {
return str[1:]
}
return str
}
// The function designed to get level-word of triples based on its position in representation when scanning from left to right
// e.g "1234", divide it into triples: "1" and "234"
// getKeyword(1) -> "" : keyword for first triple when scanning from right to left
// getKeyword(2) -> "min" : keyword for second triple when scanning from right to left
func getKeyword(position int) (keyword string, err error) {
switch position {
case 1:
//first triple: 10^3
return "", nil
case 2:
return ThousandAsString, nil
case 3:
return MillionAsString, nil
case 4:
return BillionAsString, nil
case 5:
return TrillionAsString, nil
case 6:
return QuadrillionAsString, nil
case 7:
return QuintillionAsString, nil
case 8:
return SextillionAsString, nil
case 9:
return SeptillionAsString, nil
case 10:
return OctillionAsString, nil
case 11:
return NonillionAsString, nil
case 12:
return DecillionAsString, nil
case 13:
return UndecillionAsString, nil
case 14:
return DodecillionAsString, nil
case 15:
return TredecillionAsString, nil
case 16:
return CathodecillionAsString, nil
case 17:
return KendecillionAsString, nil
case 18:
return SexdecillionAsString, nil
case 19:
return SeptendecillionAsString, nil
case 20:
return OctodecillionAsString, nil
case 21:
return NovedesillionAsString, nil
case 22:
return VigintillionAsString, nil
default:
return "", ErrTooBigNumber
}
}
// The function intended to convert any sized positive integer numbers into words
func convertIntPart(strArg string) string {
str := removeSignMarkIfExists(strArg)
//used to indicate level 10^3, 10^6
pos := 1
wordBuilder := make([]string, 0)
//starting from right hand side, pick up triples and start process it
for i := len(str); i >= 0; i = i - 3 {
key, _ := getKeyword(pos)
pos++
var leftPointer int = i - 3
if leftPointer < 0 {
leftPointer = 0
}
var rightPointer int = i
tripleAsWords, _ := tripleToWord(str[leftPointer:rightPointer])
//insert triple `tripleAsWords` in the front of result
if len(tripleAsWords) != 0 {
if len(key) != 0 {
wordBuilder = append([]string{tripleAsWords, key}, wordBuilder...)
} else {
wordBuilder = append([]string{tripleAsWords}, wordBuilder...)
}
}
}
return strings.Join(wordBuilder, " ")
}
// convertOneDigitIntoWord("0") -> "sıfır"
// convertOneDigitIntoWord("1") -> "bir"
func convertOneDigitIntoWord(oneDigitWord string) (string, error) {
if len(oneDigitWord) != 1 {
return "", ErrInvalidArgument
}
if i, err := strconv.Atoi(oneDigitWord); err != nil {
return "", err
} else {
return digits[i], nil
}
}
// convertTwoDigitsIntoWord("10") -> "on"
// convertTwoDigitsIntoWord("25") -> "iyirmi beş"
func convertTwoDigitsIntoWord(twoDigitsWord string) (string, error) {
if len(twoDigitsWord) != 2 {
return "", ErrInvalidArgument
}
var textBuilder []string
var idxAt1 int
if i, err := strconv.Atoi(twoDigitsWord[1:]); err != nil {
return "", err
} else {
idxAt1 = i
}
var wordForIdxAt1 string
if idxAt1 == 0 {
wordForIdxAt1 = ""
} else {
wordForIdxAt1 = digits[idxAt1]
}
if len(wordForIdxAt1) != 0 {
textBuilder = append([]string{wordForIdxAt1}, textBuilder...)
}
var idxAt0 int
if i, err := strconv.Atoi(twoDigitsWord[0:1]); err != nil {
return "", err
} else {
idxAt0 = i
}
wordForIdxAt0 := tens[idxAt0]
if len(wordForIdxAt0) != 0 {
textBuilder = append([]string{wordForIdxAt0}, textBuilder...)
}
return strings.Join(textBuilder, " "), nil
}
// convertThreeDigitsIntoWord("390") -> "üç yüz doxsan"
// convertThreeDigitsIntoWord("125") -> "bir yüz iyirmi beş"
func convertThreeDigitsIntoWord(threeDigitsWord string) (string, error) {
if len(threeDigitsWord) != 3 {
return "", ErrInvalidArgument
}
var textBuilder []string
for i := len(threeDigitsWord) - 1; i >= 0; i-- {
var word string
switch i {
case 2:
var ValAtIdx2 int
if i, err := strconv.Atoi(threeDigitsWord[2:]); err != nil {
return "", err
} else {
ValAtIdx2 = i
}
if ValAtIdx2 != 0 {
word = digits[ValAtIdx2]
}
case 1:
var ValAtIdx1 int
if i, err := strconv.Atoi(threeDigitsWord[1:2]); err != nil {
return "", err
} else {
ValAtIdx1 = i
}
if ValAtIdx1 != 0 {
word = tens[ValAtIdx1]
} else {
word = ""
}
case 0:
var ValAtIdx0 int
if i, err := strconv.Atoi(threeDigitsWord[0:1]); err != nil {
return "", err
} else {
ValAtIdx0 = i
}
isNonZero := ValAtIdx0 != 0
var prefix string
if isNonZero {
prefix = digits[ValAtIdx0]
} else {
prefix = ""
}
if len(prefix) > 0 {
word = prefix + " " + HundredAsString
} else {
word = ""
}
default:
return "", ErrUnexpectedBehaviour
}
if len(word) != 0 {
textBuilder = append([]string{word}, textBuilder...)
}
}
return strings.Join(textBuilder, " "), nil
}
// The function intended to convert triples("1", "12", "123") into words' representation
// tripleToWord("") -> ""
// tripleToWord("1") -> "bir"
// tripleToWord("12") -> "on iki"
// tripleToWord("123") -> "bir yüz iyirmi üz"
func tripleToWord(triple string) (string, error) {
if len(triple) == 0 {
return "", nil
}
if len(triple) == 1 {
return convertOneDigitIntoWord(triple)
}
if len(triple) == 2 {
return convertTwoDigitsIntoWord(triple)
}
return convertThreeDigitsIntoWord(triple)
}