The task is to spell out a number from 0 to 999,999,999,999 in English. Despite my code being verbose, I've managed to pass 14 out of 19 tests. However, the conversions for 1_234, 1_002_345, and 987_654_621_123L have failed. The instructions suggest, Implement breaking a number up into chunks of thousands, but I might be misunderstanding the process of chunk creation. Could you offer some guidance on the approach I should take to create these chunks?
#[Java] Say Exercise
1 messages · Page 1 of 1 (latest)
Code:
public class Say {
private final Map<Integer, String> number0To19 = new HashMap<>();
private final String[] tensNames = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
private final String[] scaleNames = {"", "thousand", "million", "billion"};
public Say() {
number0To19.put(0, "zero");
number0To19.put(1, "one");
number0To19.put(2, "two");
number0To19.put(3, "three");
// From here on, store numbers and strings as pairs up to '19'
}
public String say(long number) {
if (number < 0 || number > 999_999_999_999L) {
return "Number out of range";
}
if (number < 20) {
return number0To19.get((int) number);
}
if (number < 100) {
int ten = (int) (number / 10);
int one = (int) (number % 10);
return tensNames[ten] + (one != 0 ? "-" + number0To19.get(one) : "");
}
if (number < 1000) {
int hundred = (int) (number / 100);
number %= 100;
int ten = (int) (number / 10);
int one = (int) (number % 10);
return number0To19.get(hundred) + " hundred" + (ten != 0 ? " " + tensNames[ten]: "") + (one != 0 ? "-" + number0To19.get(one): "");
}
StringBuilder result = new StringBuilder();
for (int i = scaleNames.length - 1; i >= 0; i--) {
long divisor = (long) Math.pow(1000, i);
if (number >= divisor) {
int chunk = (int) (number / divisor);
result.append(number0To19.get(chunk)).append(" ").append(scaleNames[i]);
number %= divisor;
}
}
return result.toString();
}
}
Error Message:
TEST FAILURE
Message:
expected: "one thousand two hundred thirty-four"
but was: "one thousandnull "
Exception: org.opentest4j.AssertionFailedError:
expected: "one thousand two hundred thirty-four"
but was: "one thousandnull "
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at SayTest.oneThousandTwoHundredThirtyFour(SayTest.java:84)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Error Message:
TEST FAILURE
Message:
expected: "one million two thousand three hundred forty-five"
but was: "one milliontwo thousandnull "
Exception: org.opentest4j.AssertionFailedError:
expected: "one million two thousand three hundred forty-five"
but was: "one milliontwo thousandnull "
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at SayTest.oneMillionTwoThousandThreeHundredFortyFive(SayTest.java:96)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Error Message:
TEST FAILURE
Message:
expected: "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three"
but was: "null billionnull millionnull thousandnull "
Exception: org.opentest4j.AssertionFailedError:
expected: "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three"
but was: "null billionnull millionnull thousandnull "
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at SayTest.nineHundredEightySevenBillionSixHundredFiftyFourThreeHundredTwentyOneThousandOneHundredTwentyThree(SayTest.java:109)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
What does your code do with input 1234?
Walk us through which lines are adding to the output
for (int i = scaleNames.length - 1; i >= 0; i--) {
long divisor = (long) Math.pow(1000, i);
if (number >= divisor) {
int chunk = (int) (number / divisor);
result.append(number0To19.get(chunk)).append(" ").append(scaleNames[i]);
This part is related to the processing of 1234. Currently, it handles the thousands place, but the code fails to process the remaining 234.
expected: "one thousand two hundred thirty-four"
but was: "one thousandnull "
What values of i meet the condition? What does the if body do with those values of i?
Do you not understand why your code fails or are you asking for help on how to solve this?
I think I understand why my code fails. For 1234, it handles the thousands place but does not process the remaining 234. I'm seeking a hint on how to split the string into chunks.
You already have code that can handle 234, right?
I wouldn't focus too much on that hint. It might be a bit misleading. I think it just means to have that scale list
Yes, it's implemented in the say() method.
So you can use that method to handle that chunk
Would it be better to separate the methods?
That shouldn't be necessary but wouldn't hurt.
||You can call say() with the chunk without modifying much||
There isn't a specific reason, but since only the 'say()' method was provided as guidance in the original code, I attempted to implement within that constraint.
However, following my approach, it seems like separating the thousands and those below might be better after all.
The stubs never provides helper functions. That's not meant to discourage you from defining them.
I'd like to remove my constraints and proceed towards solving the exercise.
Can you call say() with your chunk to handle converting that chunk to a string?
I can't write the code right now, but I can imagine calling the say() method to return a value.
Would that give useful results which can be used in place of those null strings?
For numbers below 1000, the tests are passing, so I think it should work well.
I'd suggest giving that a try