5
5
import java .util .ArrayDeque ;
6
6
import java .util .ArrayList ;
7
7
import java .util .Collection ;
8
- import java .util .HashMap ;
9
8
import java .util .List ;
10
- import java .util .Map ;
11
9
12
10
/**
13
11
A Java-based utility for converting English word representations of numbers
@@ -23,43 +21,76 @@ public final class WordsToNumber {
23
21
private WordsToNumber () {
24
22
}
25
23
26
- private static final Map <String , Integer > NUMBER_MAP = new HashMap <>();
27
- private static final Map <String , BigDecimal > POWERS_OF_TEN = new HashMap <>();
28
-
29
- static {
30
- NUMBER_MAP .put ("zero" , 0 );
31
- NUMBER_MAP .put ("one" , 1 );
32
- NUMBER_MAP .put ("two" , 2 );
33
- NUMBER_MAP .put ("three" , 3 );
34
- NUMBER_MAP .put ("four" , 4 );
35
- NUMBER_MAP .put ("five" , 5 );
36
- NUMBER_MAP .put ("six" , 6 );
37
- NUMBER_MAP .put ("seven" , 7 );
38
- NUMBER_MAP .put ("eight" , 8 );
39
- NUMBER_MAP .put ("nine" , 9 );
40
- NUMBER_MAP .put ("ten" , 10 );
41
- NUMBER_MAP .put ("eleven" , 11 );
42
- NUMBER_MAP .put ("twelve" , 12 );
43
- NUMBER_MAP .put ("thirteen" , 13 );
44
- NUMBER_MAP .put ("fourteen" , 14 );
45
- NUMBER_MAP .put ("fifteen" , 15 );
46
- NUMBER_MAP .put ("sixteen" , 16 );
47
- NUMBER_MAP .put ("seventeen" , 17 );
48
- NUMBER_MAP .put ("eighteen" , 18 );
49
- NUMBER_MAP .put ("nineteen" , 19 );
50
- NUMBER_MAP .put ("twenty" , 20 );
51
- NUMBER_MAP .put ("thirty" , 30 );
52
- NUMBER_MAP .put ("forty" , 40 );
53
- NUMBER_MAP .put ("fifty" , 50 );
54
- NUMBER_MAP .put ("sixty" , 60 );
55
- NUMBER_MAP .put ("seventy" , 70 );
56
- NUMBER_MAP .put ("eighty" , 80 );
57
- NUMBER_MAP .put ("ninety" , 90 );
58
-
59
- POWERS_OF_TEN .put ("thousand" , new BigDecimal ("1000" ));
60
- POWERS_OF_TEN .put ("million" , new BigDecimal ("1000000" ));
61
- POWERS_OF_TEN .put ("billion" , new BigDecimal ("1000000000" ));
62
- POWERS_OF_TEN .put ("trillion" , new BigDecimal ("1000000000000" ));
24
+ private enum NumberWord {
25
+ ZERO ("zero" , 0 ),
26
+ ONE ("one" , 1 ),
27
+ TWO ("two" , 2 ),
28
+ THREE ("three" , 3 ),
29
+ FOUR ("four" , 4 ),
30
+ FIVE ("five" , 5 ),
31
+ SIX ("six" , 6 ),
32
+ SEVEN ("seven" , 7 ),
33
+ EIGHT ("eight" , 8 ),
34
+ NINE ("nine" , 9 ),
35
+ TEN ("ten" , 10 ),
36
+ ELEVEN ("eleven" , 11 ),
37
+ TWELVE ("twelve" , 12 ),
38
+ THIRTEEN ("thirteen" , 13 ),
39
+ FOURTEEN ("fourteen" , 14 ),
40
+ FIFTEEN ("fifteen" , 15 ),
41
+ SIXTEEN ("sixteen" , 16 ),
42
+ SEVENTEEN ("seventeen" , 17 ),
43
+ EIGHTEEN ("eighteen" , 18 ),
44
+ NINETEEN ("nineteen" , 19 ),
45
+ TWENTY ("twenty" , 20 ),
46
+ THIRTY ("thirty" , 30 ),
47
+ FORTY ("forty" , 40 ),
48
+ FIFTY ("fifty" , 50 ),
49
+ SIXTY ("sixty" , 60 ),
50
+ SEVENTY ("seventy" , 70 ),
51
+ EIGHTY ("eighty" , 80 ),
52
+ NINETY ("ninety" , 90 );
53
+
54
+ private final String word ;
55
+ private final int value ;
56
+
57
+ NumberWord (String word , int value ) {
58
+ this .word = word ;
59
+ this .value = value ;
60
+ }
61
+
62
+ public static Integer getValue (String word ) {
63
+ for (NumberWord num : NumberWord .values ()) {
64
+ if (word .equals (num .word )) {
65
+ return num .value ;
66
+ }
67
+ }
68
+ return null ;
69
+ }
70
+ }
71
+
72
+ private enum PowerOfTen {
73
+ THOUSAND ("thousand" , new BigDecimal ("1000" )),
74
+ MILLION ("million" , new BigDecimal ("1000000" )),
75
+ BILLION ("billion" , new BigDecimal ("1000000000" )),
76
+ TRILLION ("trillion" , new BigDecimal ("1000000000000" ));
77
+
78
+ private final String word ;
79
+ private final BigDecimal value ;
80
+
81
+ PowerOfTen (String word , BigDecimal value ) {
82
+ this .word = word ;
83
+ this .value = value ;
84
+ }
85
+
86
+ public static BigDecimal getValue (String word ) {
87
+ for (PowerOfTen power : PowerOfTen .values ()) {
88
+ if (word .equals (power .word )) {
89
+ return power .value ;
90
+ }
91
+ }
92
+ return null ;
93
+ }
63
94
}
64
95
65
96
public static String convert (String numberInWords ) {
@@ -103,7 +134,7 @@ private static void handleConjunction(boolean prevNumWasHundred, boolean prevNum
103
134
104
135
wordDeque .addFirst (nextWord );
105
136
106
- Integer number = NUMBER_MAP . getOrDefault (nextWord , null );
137
+ Integer number = NumberWord . getValue (nextWord );
107
138
108
139
boolean isPrevWordValid = prevNumWasHundred || prevNumWasPowerOfTen ;
109
140
boolean isNextWordValid = number != null && (number >= 10 || afterNextWord == null || "point" .equals (afterNextWord ));
@@ -198,7 +229,7 @@ private static BigDecimal convertWordQueueToBigDecimal(ArrayDeque<String> wordDe
198
229
}
199
230
prevNumWasHundred = false ;
200
231
201
- BigDecimal powerOfTen = POWERS_OF_TEN . getOrDefault (word , null );
232
+ BigDecimal powerOfTen = PowerOfTen . getValue (word );
202
233
if (powerOfTen != null ) {
203
234
handlePowerOfTen (chunks , currentChunk , powerOfTen , word , prevNumWasPowerOfTen );
204
235
currentChunk = BigDecimal .ZERO ;
@@ -207,7 +238,7 @@ private static BigDecimal convertWordQueueToBigDecimal(ArrayDeque<String> wordDe
207
238
}
208
239
prevNumWasPowerOfTen = false ;
209
240
210
- Integer number = NUMBER_MAP . getOrDefault (word , null );
241
+ Integer number = NumberWord . getValue (word );
211
242
if (number != null ) {
212
243
currentChunk = handleNumber (chunks , currentChunk , word , number );
213
244
continue ;
@@ -251,7 +282,7 @@ private static String convertDecimalPart(ArrayDeque<String> wordDeque) {
251
282
252
283
while (!wordDeque .isEmpty ()) {
253
284
String word = wordDeque .poll ();
254
- Integer number = NUMBER_MAP . getOrDefault (word , null );
285
+ Integer number = NumberWord . getValue (word );
255
286
if (number == null ) {
256
287
throw new WordsToNumberException (WordsToNumberException .ErrorType .UNEXPECTED_WORD_AFTER_POINT , word );
257
288
}
0 commit comments