Now, I have extended my program taking some answers in the previous iteration into account:
package com.github.coderodde.fun;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class LongSpeller {
private static final class BigNumber {
private final long size;
private final String name;
private BigNumber(long size, String name) {
this.size = size;
this.name = name;
}
public long getSize() {
return size;
}
public String getName() {
return name;
}
}
private static final class Pair {
private final String name;
private final Long number;
Pair(String name, Long number) {
this.name = name;
this.number = number;
}
}
private static final BigNumber[] BIG_NUMBERS = {
new BigNumber(1L, ""),
new BigNumber(1_000L, "thousand"),
new BigNumber(1_000_000L, "million"),
new BigNumber(1_000_000_000L, "billion"),
new BigNumber(1_000_000_000_000L, "trillion"),
new BigNumber(1_000_000_000_000_000L, "quadrillion"),
new BigNumber(1_000_000_000_000_000_000L, "quintillion"),
};
private static final Map<Long, String> WORDS = new HashMap<>();
static {
WORDS.put(1L, "one");
WORDS.put(2L, "two");
WORDS.put(3L, "three");
WORDS.put(4L, "four");
WORDS.put(5L, "five");
WORDS.put(6L, "six");
WORDS.put(7L, "seven");
WORDS.put(8L, "eight");
WORDS.put(9L, "nine");
WORDS.put(10L, "ten");
WORDS.put(11L, "eleven");
WORDS.put(12L, "twelve");
WORDS.put(13L, "thirteen");
WORDS.put(14L, "fourteen");
WORDS.put(15L, "fifteen");
WORDS.put(16L, "sixteen");
WORDS.put(17L, "seventeen");
WORDS.put(18L, "eighteen");
WORDS.put(19L, "nineteen");
WORDS.put(20L, "twenty");
WORDS.put(30L, "thirty");
WORDS.put(40L, "fourty");
WORDS.put(50L, "fifty");
WORDS.put(60L, "sixty");
WORDS.put(70L, "seventy");
WORDS.put(80L, "eighty");
WORDS.put(90L, "ninety");
}
/**
* Spells an input long value as text. For example, for input 2048, the
* return value will be "two thousand forty-eight".
*
* @param num the value to spell.
* @return text representation of {@code num}.
*/
public static String spell(long num) {
if (num == Long.MIN_VALUE) {
return "(not supported)";
} else if (num == 0) {
return "zero";
}
StringBuilder sb = new StringBuilder();
if (num < 0) {
sb.append("minus ");
num = -num;
}
int orderOfMagnitude = 0;
Deque<Pair> parts = new ArrayDeque<>();
do {
parts.addLast(
new Pair(BIG_NUMBERS[orderOfMagnitude++].getName(),
num % 1_000L));
num /= 1_000L;
} while (num > 0);
while (parts.size() > 1) {
Pair pair = parts.removeLast();
convertHundredsImpl(
pair.number,
sb).append(" ")
.append(pair.name)
.append(" ");
}
convertHundredsImpl(parts.removeLast().number, sb);
return sb.toString().trim();
}
// Converts a num in range [0, 999] to the human readable string:
private static StringBuilder
convertHundredsImpl(long num, StringBuilder sb) {
long hundreds = num / 100;
num -= 100 * hundreds;
if (hundreds > 0) {
sb.append(WORDS.get(hundreds));
sb.append(" hundred ");
}
if (num > 0) {
String tensString = WORDS.get(num);
if (tensString == null) {
long units = num % 10;
num -= units;
sb.append(WORDS.get(num));
sb.append("-");
sb.append(WORDS.get(units));
} else {
sb.append(tensString);
}
}
return sb;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLong()) {
long num = scanner.nextLong();
String s = spell(num);
System.out.println(s);
}
}
}
Critique request
So what do you think? Am I getting it right?
do..while
loop inspell
when a normalwhile
loop would suffice? \$\endgroup\$