55import java .util .ArrayDeque ;
66import java .util .ArrayList ;
77import java .util .Collection ;
8- import java .util .HashMap ;
98import java .util .List ;
10- import java .util .Map ;
119
1210/**
1311 A Java-based utility for converting English word representations of numbers
@@ -23,43 +21,76 @@ public final class WordsToNumber {
2321 private WordsToNumber () {
2422 }
2523
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+ }
6394 }
6495
6596 public static String convert (String numberInWords ) {
@@ -103,7 +134,7 @@ private static void handleConjunction(boolean prevNumWasHundred, boolean prevNum
103134
104135 wordDeque .addFirst (nextWord );
105136
106- Integer number = NUMBER_MAP . getOrDefault (nextWord , null );
137+ Integer number = NumberWord . getValue (nextWord );
107138
108139 boolean isPrevWordValid = prevNumWasHundred || prevNumWasPowerOfTen ;
109140 boolean isNextWordValid = number != null && (number >= 10 || afterNextWord == null || "point" .equals (afterNextWord ));
@@ -198,7 +229,7 @@ private static BigDecimal convertWordQueueToBigDecimal(ArrayDeque<String> wordDe
198229 }
199230 prevNumWasHundred = false ;
200231
201- BigDecimal powerOfTen = POWERS_OF_TEN . getOrDefault (word , null );
232+ BigDecimal powerOfTen = PowerOfTen . getValue (word );
202233 if (powerOfTen != null ) {
203234 handlePowerOfTen (chunks , currentChunk , powerOfTen , word , prevNumWasPowerOfTen );
204235 currentChunk = BigDecimal .ZERO ;
@@ -207,7 +238,7 @@ private static BigDecimal convertWordQueueToBigDecimal(ArrayDeque<String> wordDe
207238 }
208239 prevNumWasPowerOfTen = false ;
209240
210- Integer number = NUMBER_MAP . getOrDefault (word , null );
241+ Integer number = NumberWord . getValue (word );
211242 if (number != null ) {
212243 currentChunk = handleNumber (chunks , currentChunk , word , number );
213244 continue ;
@@ -251,7 +282,7 @@ private static String convertDecimalPart(ArrayDeque<String> wordDeque) {
251282
252283 while (!wordDeque .isEmpty ()) {
253284 String word = wordDeque .poll ();
254- Integer number = NUMBER_MAP . getOrDefault (word , null );
285+ Integer number = NumberWord . getValue (word );
255286 if (number == null ) {
256287 throw new WordsToNumberException (WordsToNumberException .ErrorType .UNEXPECTED_WORD_AFTER_POINT , word );
257288 }
0 commit comments